使用promises进行编码时,正确的模式是什么,可以在承诺链中访问很久以前的数据?
例如:
do_A.then(do_B).then(do_C).then(do_D).then(do_E_WithTheDataComingFrom_A_And_C_OnlyWhen_D_IsSuccesfullyCompleted)
我目前的解决方案:通过链路传递单个JSON结构,并让每个步骤填充它。 有关于此的任何意见吗?
答案 0 :(得分:3)
我不认为有一个"正确"这种模式。你的解决方案听起来很整洁,然而,它有点紧密耦合。它可能适合您的情况,但我认为它有一些问题作为一般模式:
参与的步骤需要就收集对象的结构达成一致。
每个步骤至少需要参与对象的转发,如果链很长并且偶尔需要以前的数据,这可能会变得乏味。这对于插入非你写的步骤也是不灵活的(链接并不总是线性地发生)。
不同地说:除非do_A | B | C | D和do_E在您的控制之下,否则您需要使用样板包装它们以将您的收集器对象存储在闭包中并转换为功能'自然输入和结果,因为功能不会在" in"你的模式。
另一方面,如果函数 ,那么这些步骤之间的数据依赖关系实际上已隐藏在函数内部。这可能看起来很干净,但可能会成为维护问题。例如:如果这是一个团队项目,那么有人可能会认为他们可以重新排序您的步骤,在调用模式中没有任何线索,do_E需要什么输入。
我建议使用闭包更直接的方法:
var a, c;
do_A()
.then(function(result) { a = result; return do_B(); })
.then(do_C)
.then(function(result) { c = result; return do_D(); })
.then(function() {
return do_E_WithTheDataComingFrom_A_And_C_OnlyWhen_D_Succeeds(a, c);
})
.catch(failed);
没有要定义的收集器对象; do_A | B | C | D和do_E可以是通用函数,不知道任何模式;除非依赖返回的数据(do_B和do_D),否则没有样板;并且数据依赖性(a和c)是显式的。
答案 1 :(得分:2)
是的,这是通过操作链接状态的正确方法。
链接.then
语句非常常见,通常是我们在处理事物时的构建块。这是承诺的核心。
你所做的是正确和惯用的。
对于好奇的精神,让我们展示一下。
为了验证这一点 - 我们可以查看承诺规范。
我们要验证:
then
返回的具有相同原因的下一个承诺让我们使用specification - 特别是.then
按顺序验证这些:
7.1然后必须返回一个承诺[3.3]。
太棒了,让我们确认它也在完整填充物上链接
如果onFulfilled或onRejected返回值x,请运行Promise Resolution Procedure> [[Resolve]](promise2,x)。
很好,所以我们知道当我们的promise解析或拒绝时,我们会使用适当的参数调用then
处理程序。因此,.then(do_A).then(do_B)
将始终以假设do_A
结算。
7.iv。如果onRejected不是函数且promise1被拒绝,则必须以相同的原因拒绝promise2。
很好,所以它会拒绝并调用onRejected
如果它存在,如果不存在则链接。
then
返回的下一个承诺,原因相同我们刚刚在2中介绍过。
再次
如果onFulfilled或onRejected返回值x,请运行Promise Resolution Procedure [[Resolve]](promise2,x)。
因此,如果您设置onFulfilled,它将运行解析过程。决议过程本身决定:
承诺解决程序是一个抽象操作,将promise和值作为输入,我们将其表示为[[Resolve]](promise,x)。如果x是一个可能的,它会尝试使x采用x的状态,假设x的行为至少有点像promise。否则,它使用值x履行承诺。
如果/当使用值y调用resolvePromise时,运行[[Resolve]](promise,y)。
其中y是x的返回值。
大!所以它有效。