Tôi đang tạo một ứng dụng Reac.js với kiến trúc thông lượng và tôi đang cố gắng tìm ra yêu cầu dữ liệu từ máy chủ ở đâu và khi nào. Có một ví dụ cho điều này. (Không phải ứng dụng TODO!)
Tôi đang tạo một ứng dụng Reac.js với kiến trúc thông lượng và tôi đang cố gắng tìm ra yêu cầu dữ liệu từ máy chủ ở đâu và khi nào. Có một ví dụ cho điều này. (Không phải ứng dụng TODO!)
Câu trả lời:
Tôi là một người ủng hộ lớn việc đưa các hoạt động ghi async vào các trình tạo hành động và các hoạt động đọc async trong cửa hàng. Mục tiêu là giữ cho mã sửa đổi trạng thái cửa hàng trong các trình xử lý hành động hoàn toàn đồng bộ; điều này làm cho chúng đơn giản để lý do và đơn giản để kiểm tra đơn vị. Để ngăn nhiều yêu cầu đồng thời đến cùng một điểm cuối (ví dụ: đọc hai lần), tôi sẽ chuyển việc xử lý yêu cầu thực tế sang một mô-đun riêng sử dụng lời hứa để ngăn chặn nhiều yêu cầu; ví dụ:
class MyResourceDAO {
get(id) {
if (!this.promises[id]) {
this.promises[id] = new Promise((resolve, reject) => {
// ajax handling here...
});
}
return this.promises[id];
}
}
Trong khi đọc trong cửa hàng liên quan đến các chức năng không đồng bộ, có một cảnh báo quan trọng là các cửa hàng không tự cập nhật trong trình xử lý không đồng bộ, mà thay vào đó, kích hoạt một hành động và chỉ thực hiện một hành động khi có phản hồi. Người xử lý cho hành động này cuối cùng thực hiện sửa đổi trạng thái thực tế.
Ví dụ, một thành phần có thể làm:
getInitialState() {
return { data: myStore.getSomeData(this.props.id) };
}
Cửa hàng sẽ có một phương thức được thực hiện, có lẽ, một cái gì đó như thế này:
class Store {
getSomeData(id) {
if (!this.cache[id]) {
MyResurceDAO.get(id).then(this.updateFromServer);
this.cache[id] = LOADING_TOKEN;
// LOADING_TOKEN is a unique value of some kind
// that the component can use to know that the
// value is not yet available.
}
return this.cache[id];
}
updateFromServer(response) {
fluxDispatcher.dispatch({
type: "DATA_FROM_SERVER",
payload: {id: response.id, data: response}
});
}
// this handles the "DATA_FROM_SERVER" action
handleDataFromServer(action) {
this.cache[action.payload.id] = action.payload.data;
this.emit("change"); // or whatever you do to re-render your app
}
}
flux
được đưa vào các cửa hàng sau khi xây dựng, vì vậy không có cách nào tuyệt vời để có được các hành động trong phương thức khởi tạo. Bạn có thể tìm thấy một số ý tưởng hay từ libs thông lượng đẳng hướng của Yahoo; Đây là điều Fluxxor v2 nên hỗ trợ tốt hơn. Vui lòng gửi email cho tôi nếu bạn muốn trò chuyện về điều này nhiều hơn.
data: result
nên data : data
, phải không? không có là result
. có lẽ tốt hơn để đổi tên param dữ liệu thành tải trọng hoặc một cái gì đó tương tự.
Fluxxor có một ví dụ về giao tiếp không đồng bộ với API.
Bài đăng trên blog này đã nói về nó và đã được đăng trên blog của React.
Tôi thấy đây là một câu hỏi rất quan trọng và khó chưa được trả lời rõ ràng, vì đồng bộ hóa phần mềm frontend với phần phụ trợ vẫn còn là một nỗi đau.
Các yêu cầu API có nên được thực hiện trong các thành phần JSX không? Cửa hàng? Nơi khác?
Thực hiện các yêu cầu trong cửa hàng có nghĩa là nếu 2 cửa hàng cần cùng một dữ liệu cho một hành động nhất định, họ sẽ đưa ra 2 yêu cầu tương tự (trừ khi bạn giới thiệu phụ thuộc giữa các cửa hàng, điều mà tôi thực sự không thích )
Trong trường hợp của tôi, tôi đã thấy điều này rất tiện dụng để đặt lời hứa Q làm trọng tải hành động vì:
Ajax là EVIL
Tôi nghĩ Ajax sẽ ngày càng ít được sử dụng trong tương lai gần bởi vì rất khó để lý do. Đúng cách? Xem xét các thiết bị như là một phần của hệ thống phân tán, tôi không biết lần đầu tiên tôi bắt gặp ý tưởng này (có thể trong video Chris Granger đầy cảm hứng này ).
Hãy suy nghĩ về nó. Bây giờ để có khả năng mở rộng, chúng tôi sử dụng các hệ thống phân tán có tính nhất quán cuối cùng làm công cụ lưu trữ (vì chúng tôi không thể đánh bại định lý CAP và thường chúng tôi muốn có sẵn). Các hệ thống này không đồng bộ hóa thông qua việc bỏ phiếu cho nhau (ngoại trừ có thể cho các hoạt động đồng thuận?) Mà sử dụng các cấu trúc như CRDT và nhật ký sự kiện để làm cho tất cả các thành viên của hệ thống phân tán cuối cùng (các thành viên sẽ hội tụ cùng một dữ liệu, trong một thời gian đủ) .
Bây giờ hãy nghĩ về một thiết bị di động hoặc một trình duyệt. Nó chỉ là một thành viên của hệ thống phân tán có thể bị ảnh hưởng bởi độ trễ mạng và phân vùng mạng. (tức là bạn đang sử dụng điện thoại thông minh của mình trên tàu điện ngầm)
Nếu chúng ta có thể xây dựng cơ sở dữ liệu phân vùng mạng và tốc độ mạng (ý tôi là chúng ta vẫn có thể thực hiện thao tác ghi vào một nút bị cô lập), chúng ta có thể xây dựng phần mềm frontend (di động hoặc máy tính để bàn) lấy cảm hứng từ các khái niệm này, hoạt động tốt với chế độ ngoại tuyến được hỗ trợ của hộp không có tính năng ứng dụng không có sẵn.
Tôi nghĩ rằng chúng ta nên thực sự truyền cảm hứng cho chính mình về cách cơ sở dữ liệu đang hoạt động để kiến trúc các ứng dụng lối vào của chúng ta. Một điều cần chú ý là các ứng dụng này không thực hiện các yêu cầu POST và PUT và GET ajax để gửi dữ liệu cho nhau, mà sử dụng nhật ký sự kiện và CRDT để đảm bảo tính nhất quán cuối cùng.
Vậy tại sao không làm điều đó trên frontend? Lưu ý rằng phụ trợ đã di chuyển theo hướng đó, với các công cụ như Kafka được áp dụng rộng rãi bởi những người chơi lớn. Điều này cũng liên quan đến Nguồn cung cấp sự kiện / CQRS / DDD.
Kiểm tra những bài viết tuyệt vời này từ các tác giả Kafka để thuyết phục bản thân:
Có lẽ chúng ta có thể bắt đầu bằng cách gửi lệnh đến máy chủ và nhận một luồng các sự kiện máy chủ (thông qua websockets cho ví dụ), thay vì thực hiện các yêu cầu Ajax.
Tôi chưa bao giờ thấy thoải mái với các yêu cầu của Ajax. Khi chúng tôi React, các nhà phát triển có xu hướng trở thành các lập trình viên chức năng. Tôi nghĩ thật khó để lý giải về dữ liệu cục bộ được coi là "nguồn sự thật" của ứng dụng lối vào của bạn, trong khi nguồn sự thật thực sự có trên cơ sở dữ liệu máy chủ và nguồn sự thật "cục bộ" của bạn có thể đã lỗi thời khi bạn nhận được nó, và sẽ không bao giờ hội tụ đến nguồn thực của giá trị thật trừ khi bạn nhấn một số nút Làm mới khập khiễng ... Đây có phải là kỹ thuật không?
Tuy nhiên, vẫn còn một chút khó khăn để thiết kế một thứ như vậy vì một số lý do rõ ràng:
this.dispatch("LOAD_DATA", {dataPromise: yourPromiseHere});
Bạn có thể gọi dữ liệu trong trình tạo hành động hoặc cửa hàng. Điều quan trọng là không xử lý trực tiếp phản hồi mà tạo ra một hành động trong cuộc gọi lại lỗi / thành công. Xử lý các phản ứng trực tiếp trong cửa hàng dẫn đến một thiết kế dễ vỡ hơn.
Tôi đã sử dụng ví dụ của Binary Muse từ ví dụ Fluxxor ajax . Đây là ví dụ rất đơn giản của tôi bằng cách sử dụng cùng một cách tiếp cận.
Tôi có một sản phẩm đơn giản lưu trữ một số hành động sản phẩm và thành phần xem bộ điều khiển có các thành phần phụ đáp ứng tất cả các thay đổi được thực hiện cho cửa hàng sản phẩm . Ví dụ sản phẩm thanh trượt , sản phẩm-list và product-search linh kiện.
Khách hàng sản phẩm giả
Đây là ứng dụng khách giả mà bạn có thể thay thế để gọi một sản phẩm trả về điểm cuối thực tế.
var ProductClient = {
load: function(success, failure) {
setTimeout(function() {
var ITEMS = require('../data/product-data.js');
success(ITEMS);
}, 1000);
}
};
module.exports = ProductClient;
Cửa hàng sản phẩm
Đây là Cửa hàng sản phẩm, rõ ràng đây là một cửa hàng rất tối thiểu.
var Fluxxor = require("fluxxor");
var store = Fluxxor.createStore({
initialize: function(options) {
this.productItems = [];
this.bindActions(
constants.LOAD_PRODUCTS_SUCCESS, this.onLoadSuccess,
constants.LOAD_PRODUCTS_FAIL, this.onLoadFail
);
},
onLoadSuccess: function(data) {
for(var i = 0; i < data.products.length; i++){
this.productItems.push(data.products[i]);
}
this.emit("change");
},
onLoadFail: function(error) {
console.log(error);
this.emit("change");
},
getState: function() {
return {
productItems: this.productItems
};
}
});
module.exports = store;
Bây giờ các hành động của sản phẩm, thực hiện yêu cầu AJAX và thực hiện thành công hành động LOAD_PRODUCTS_SUCCESS trả lại sản phẩm cho cửa hàng.
Hoạt động sản phẩm
var ProductClient = require("../fake-clients/product-client");
var actions = {
loadProducts: function() {
ProductClient.load(function(products) {
this.dispatch(constants.LOAD_PRODUCTS_SUCCESS, {products: products});
}.bind(this), function(error) {
this.dispatch(constants.LOAD_PRODUCTS_FAIL, {error: error});
}.bind(this));
}
};
module.exports = actions;
Vì vậy, gọi this.getFlux().actions.productActions.loadProducts()
từ bất kỳ thành phần nghe cửa hàng này sẽ tải các sản phẩm.
Bạn có thể tưởng tượng có các hành động khác nhau mặc dù sẽ phản ứng với các tương tác của người dùng như addProduct(id)
removeProduct(id)
vv ... theo cùng một mẫu.
Hy vọng rằng ví dụ này sẽ giúp một chút, vì tôi thấy điều này hơi khó thực hiện, nhưng chắc chắn đã giúp giữ cho các cửa hàng của tôi đồng bộ 100%.
Tôi đã trả lời một câu hỏi liên quan ở đây: Làm thế nào để xử lý các cuộc gọi api lồng nhau trong thông lượng
Hành động không được coi là những thứ gây ra thay đổi. Họ được cho là giống như một tờ báo thông báo về ứng dụng của một sự thay đổi trong thế giới bên ngoài, và sau đó ứng dụng này phản ứng với tin tức đó. Các cửa hàng gây ra thay đổi trong chính họ. Hành động chỉ cần thông báo cho họ.
Bill Fisher, người tạo ra Flux https://stackoverflow.com/a/26581808/4258088
Những gì bạn về cơ bản nên làm là, thông qua hành động những dữ liệu bạn cần. Nếu cửa hàng được thông báo bằng hành động, nó sẽ quyết định xem có cần lấy một số dữ liệu hay không.
Cửa hàng phải chịu trách nhiệm tích lũy / tìm nạp tất cả dữ liệu cần thiết. Tuy nhiên, điều quan trọng cần lưu ý là sau khi cửa hàng yêu cầu dữ liệu và nhận được phản hồi, nó sẽ tự kích hoạt một hành động với dữ liệu được tìm nạp, trái ngược với việc xử lý / lưu trực tiếp phản hồi của cửa hàng.
Một cửa hàng có thể trông giống như thế này:
class DataStore {
constructor() {
this.data = [];
this.bindListeners({
handleDataNeeded: Action.DATA_NEEDED,
handleNewData: Action.NEW_DATA
});
}
handleDataNeeded(id) {
if(neededDataNotThereYet){
api.data.fetch(id, (err, res) => {
//Code
if(success){
Action.newData(payLoad);
}
}
}
}
handleNewData(data) {
//code that saves data and emit change
}
}
Đây là của tôi về điều này: http://www.thedreaming.org/2015/03/14/react-ajax/
Mong rằng sẽ giúp. :)