我正在使用Flux架构创建一个React.js应用程序,我正在尝试找出从服务器请求数据的何时何地。是否有相关示例可供参考?(不是TODO应用程序!)
我正在使用Flux架构创建一个React.js应用程序,我正在尝试找出从服务器请求数据的何时何地。是否有相关示例可供参考?(不是TODO应用程序!)
我十分支持在action creators中放置异步写操作,在store中放置异步读操作。这样做的目的是将store状态修改代码保持在完全同步的action处理程序中;这使得它们易于理解和单元测试。为了防止对同一端点进行多次同时请求(例如,重复读取),我会将实际请求处理移到一个单独的模块中,并使用promises来防止多次请求;例如:
class MyResourceDAO {
get(id) {
if (!this.promises[id]) {
this.promises[id] = new Promise((resolve, reject) => {
// ajax handling here...
});
}
return this.promises[id];
}
}
尽管存储器中的读取涉及异步函数,但存在一个重要的注意点,即存储器不会在异步处理程序中自行更新,而是在响应到达时触发一个操作,仅触发一个操作。对于此操作的处理程序最终执行实际的状态修改。
例如,组件可能会执行:
getInitialState() {
return { data: myStore.getSomeData(this.props.id) };
}
商店可能已经实现了一个方法,类似于这样:
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
}
}
Fluxxor有一个与API进行异步通信的示例。
这个博客文章讨论了它,并在React的博客上得到了推荐。
Ajax很糟糕
我认为在不久的将来,Ajax将越来越少被使用,因为它很难理解。 正确的方法?将设备视为分布式系统的一部分 我不知道我最初从哪里得到这个想法(也许是在这个启发人心的Chris Granger视频中)。
想想看。现在,为了可扩展性,我们使用具有最终一致性作为存储引擎的分布式系统(因为我们无法打败CAP定理,而且我们经常希望可用)。这些系统不通过轮询彼此进行同步(除了可能进行共识操作?),而是使用类似CRDT和事件日志的结构,使分布式系统的所有成员最终一致(成员将在足够的时间内收敛到相同的数据)。
现在想想移动设备或浏览器是什么。它只是分布式系统的一个成员,可能会遭受网络延迟和网络分区。(即您在地铁上使用智能手机)
如果我们能够构建网络分区和网络速度容错的数据库(我的意思是我们仍然可以对隔离节点执行写操作),那么我们可能可以构建受这些概念启发的前端软件(移动或桌面),这些软件支持离线模式,无需应用程序功能不可用。也许我们可以通过向服务器发送命令,并通过流接收服务器事件(例如通过Websockets),而不是触发Ajax请求。
我从未对Ajax请求感到非常舒适。由于我们React开发人员倾向于成为函数式程序员,因此我认为很难推断出本地数据应该是您前端应用程序的“真相来源”,而真正的真相来源实际上在服务器数据库上,您的“本地”真相来源可能已经过时,除非您按下某些无聊的刷新按钮,否则永远不会趋近于真正的真相值......这是工程学吗?
但是,由于一些明显的原因,设计这样的东西仍然有些困难:
您的移动/浏览器客户端资源有限,不能保证所有数据都存储在本地(因此有时需要使用ajax请求轮询重内容)。为了安全起见,您的客户端不应看到分布式系统的所有数据,因此需要对其接收到的事件进行过滤。this.dispatch("LOAD_DATA", {dataPromise: yourPromiseHere});
的事情。 - Sebastien Lorber你可以在action creators或stores中调用数据。重要的是不直接处理响应,而是在错误/成功回调中创建一个操作。在store中直接处理响应会导致设计更加脆弱。
var ProductClient = {
load: function(success, failure) {
setTimeout(function() {
var ITEMS = require('../data/product-data.js');
success(ITEMS);
}, 1000);
}
};
module.exports = ProductClient;
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;
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;
this.getFlux().actions.productActions.loadProducts()
将加载产品。addProduct(id)
、removeProduct(id)
等... 遵循相同的模式。我在这里回答了一个相关的问题:如何在Flux中处理嵌套的API调用
Actions不应该是引起变化的东西。它们应该像报纸一样通知应用程序外部世界的变化,然后应用程序响应这个新闻。存储会导致自身的变化。操作只是通知他们。
Flux的创建者Bill Fisherhttps://dev59.com/SV8d5IYBdhLWcg3wpzlf#26581808说过,你基本上需要做的就是通过操作说明你需要什么数据。如果存储通过操作得到通知,它应该决定是否需要获取一些数据。
存储应负责累积/获取所有所需数据。但重要的是要注意,在存储请求数据并获得响应后,它应该使用已获取的数据触发一个操作,而不是直接处理/保存响应。
存储可能看起来像这样:
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
}
}
flux
是在构建之后注入到store中的,所以很难在initialize方法中获取actions。你可能会从Yahoo的同构流库中获得一些好的想法;这是Fluxxor v2应该更好支持的内容。如果您想进一步交流,请随时给我发电子邮件。 - Michelle Tilleydata: result
应该改为data: data
,对吧?没有result
。或许最好将data
参数重命名为payload
或其他类似的名称。 - oligofrenprimaryKey
来自哪里更加明显(它在服务器响应中)。 - Michelle Tilley