Asynchronous 回流中的排队异步操作
当将RefluxJS存储与异步操作一起使用时,很容易在操作之间产生竞争条件 对问题的抽象描述 例如,我们的存储处于状态X。一个异步操作A从X调用,在它完成之前,另一个异步操作B也从X调用。从这里开始,无论哪个操作先完成,它都会出错Asynchronous 回流中的排队异步操作,asynchronous,refluxjs,Asynchronous,Refluxjs,当将RefluxJS存储与异步操作一起使用时,很容易在操作之间产生竞争条件 对问题的抽象描述 例如,我们的存储处于状态X。一个异步操作A从X调用,在它完成之前,另一个异步操作B也从X调用。从这里开始,无论哪个操作先完成,它都会出错 B首先完成状态Y1,a最后完成并用Y2覆盖状态Y1 A首先以状态Y2结束,B用Y1覆盖Y2 期望的行为是: A B X -> Y -> Z 其中,B不是基于X,而是基于Y,并导致一致的Z状态,而不是基于相同状态的两个动作,导致不一致的状态:
A B
X -> Y -> Z
其中,B不是基于X,而是基于Y,并导致一致的Z状态,而不是基于相同状态的两个动作,导致不一致的状态:
A
X -> Y1 .--> Y2
\ /
'----'
B
该问题的一个实例
我写了一个关于我所讨论的问题的最小工作示例,使用Node运行
var Q=require('Q');
var回流=需要(“回流”);
var RefluxPromise=要求(“reflux-promise”);
使用(RefluxPromise(Q.Promise));
var AsyncActions=reflow.createActions({
'add':{asyncResult:true}
});
var AsyncStore=reflow.createStore({
init:函数(){
//国家
这个计数器=0;
AsyncActions.add.ListendPromise(this.onAdd,this);
},
//延迟后的增量计数器
onAdd:函数(n,延迟){
var=这个;
返回apiAdd(this.counter,n,delay)
.then(函数(新计数器){
that.counter=newCounter;
那个.触发器(那个.计数器);
});
}
});
//模拟一个API调用,该调用进行add计算。延迟
//参数用于测试。
//@return{Promise}
函数apiAdd(计数器,n,延迟){
var result=Q.defer();
setTimeout(函数(){
结果.解析(计数器+n);
},延误);
回报结果。承诺;
}
//记录存储触发器
listen(console.log.bind(未定义,'Triggered');
//1秒后添加3。
AsyncActions.add(31000);
//几乎立即添加100
AsyncActions.add(100,1);
//控制台输出:
//>触发100
//>触发3
//所需输出(排队操作):
//>触发3
//>触发103
使用package.json中的这些依赖项
{
“依赖项”:{
“q”:“^1.3.0”,
“回流”:“^0.3”,
“回流承诺”:“^1”
}
}
问题的性质
我期望RefluxJS对操作进行排队,但事实并非如此。因此,我正在寻找一种方法来正确地安排这些行动。但是,即使我设法以某种方式将这些操作排队(因此在A之后发出B),我如何确定,当A完成时,发出B仍然是有效的操作?
也许我一开始就用错了RefluxJS,而这种情况在一个结构合理的应用程序中是不会发生的
异步操作排队(假设在回流应用程序中可以)是解决方案吗?或者我们应该首先设法避免这些情况吗?你的例子似乎更像是一个关于“真理之源”概念的问题,而不是其他任何问题。您只存储数字客户端的当前状态,但只有在收到服务器端对其执行的操作的确认后才对其进行更新 当然,这会造成问题。你以一种奇怪的方式将数字的行为和数字的存储混合在一起,在任何给定时刻,数字的真实性都没有单一的来源。在动作被称为“完成”的这段时间里,这是一个悬而未决的问题……这是不好的 在客户端存储号码,每次添加时,直接添加号码,然后告诉服务器端新号码是什么。。。(即,当客户端运行时,客户端负责作为数字的真实来源) 或者将号码存储在服务器端,每次您使用客户端的操作将其更新时,服务器都会返回新的更新号码。(即数字的真实来源完全是服务器端) 然后,即使发生种族问题,你仍然有一个数字是什么的真相来源,这个来源可以被检查和确认。例如,如果服务器端持有数字的真实来源,那么API也可以在每次返回该值时返回该值状态的时间戳,并且您可以对照从API获得的最后一个值进行检查,以确保您实际使用的是最新的值