Javascript 访问以前履行的承诺会导致承诺链

Javascript 访问以前履行的承诺会导致承诺链,javascript,promise,Javascript,Promise,当使用承诺编码时,访问承诺链中很久以前的数据的正确模式是什么 例如: do_A.then(do_B).then(do_C).then(do_D).then(do_E_WithTheDataComingFrom_A_And_C_OnlyWhen_D_IsSuccesfullyCompleted) 我目前的解决方案是:通过链传递单个JSON结构,并让每个步骤填充它。 对此有什么看法吗?是的,这是将状态与动作联系起来的正确方法 链接。然后语句是非常常见的,并且通常是我们在传递信息时的构建块。这是承诺

当使用承诺编码时,访问承诺链中很久以前的数据的正确模式是什么

例如:

do_A.then(do_B).then(do_C).then(do_D).then(do_E_WithTheDataComingFrom_A_And_C_OnlyWhen_D_IsSuccesfullyCompleted)
我目前的解决方案是:通过链传递单个JSON结构,并让每个步骤填充它。
对此有什么看法吗?

是的,这是将状态与动作联系起来的正确方法

链接
。然后
语句是非常常见的,并且通常是我们在传递信息时的构建块。这是承诺的核心

你所做的既正确又地道


出于好奇的精神,让我们展示一下

为了验证这一点,我们可以检查promises规范

我们要核实:

  • It链
  • 在拒绝的情况下,它不会调用链接中的处理程序
  • 它拒绝了
    然后
    返回的下一个承诺,原因相同
  • 它通过返回值按顺序执行
  • 让我们使用-尤其是
    ,按顺序验证这些

    1.It链 7.1然后必须返回承诺[3.3]

    太好了,让我们验证一下它是否也在满填充时链接

    如果OnCompleted或onRejected返回值x,请运行承诺解决过程>[[Resolve]](promise2,x)

    很好,所以我们知道,当我们的承诺被解析或拒绝时,我们的
    然后
    处理程序就会被适当的参数调用。所以
    。然后(do_A)。然后(do_B)
    将始终工作,假设
    do_A
    解决

    2.在拒绝的情况下,它不会调用链接中的处理程序 7.iv。如果onRejected不是一个函数,并且promise1被拒绝,promise2必须以相同的理由被拒绝

    太好了,所以它拒绝并调用
    onRejected
    ,如果它在那里,如果它不在,它就会链接

    3.它拒绝了
    然后
    返回的下一个承诺,原因相同
    我们刚刚在第2章中谈到了这一点

    4.它通过返回值按顺序执行。 又是这样

    如果OnCompleted或onRejected返回值x,则运行承诺解决过程[[Resolve]](promise2,x)

    因此,如果设置为onCompleted,它将运行解析过程。处置过程本身规定:

    承诺解析过程是以承诺和值作为输入的抽象操作,我们将其表示为[[Resolve]](承诺,x)。如果x是一个表,那么它试图使promise采用x的状态,假设x的行为至少有点像promise。否则,它将以x值履行承诺

    如果使用值y调用resolvePromise,请运行[[Resolve]](promise,y)

    其中y是x的返回值

    太好了!所以它是有效的。

    我不认为有一个“正确”的模式。您的解决方案听起来不错,但是,它有点紧密耦合。它可能对您的情况非常有效,但我认为它作为一种通用模式存在一些问题:

  • 参与的步骤需要就收集器对象的结构达成一致

  • 每一步都至少需要参与对象的转发,如果链很长,并且偶尔需要以前的数据,那么转发会变得单调乏味。这对于插入非您编写的步骤也是不灵活的(链接并不总是线性发生)

  • 换言之:除非do|A | B | C | D和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)是显式的