可以(应该)JavaScript承诺用于共同依赖的功能吗?

时间:2015-01-11 21:04:23

标签: javascript asynchronous promise

Promise非常适合将某些内容附加到异步调用的 end ,而异步调用不需要知道其关注者。可以承诺在更常见或复杂的情况下使用,在异步调用中需要回调,如果是这样,它可以提供相同级别的分离吗?

例如,假设你有两个功能a& b执行顺序从a转移到b并返回两次。

使用回调:

function a() {
    console.log('a1');
    b(function(b2) { 
        requestAnimationFrame(function() { 
            console.log('a2'); 
            b2(); 
        }); 
    });
}

function b(a2) {
    console.log('b1');
    a2(function() { 
        requestAnimationFrame(function() { 
            console.log('b2'); 
        }); 
    });
}

this is something

我知道这两个函数可以分成两部分并与promises结合在一起,但这可能会丢失在a1 / b1中设置的重要的昂贵计算范围变量,或导致冗余代码甚至更难遵循执行顺序。

问题是,是否可以使用promises重写此代码,使得b()不需要了解a(),但确实为调用者提供了在 b()完成执行?

1 个答案:

答案 0 :(得分:2)

在回答之前,我稍微修改了您的示例以突出显示执行流程:

function a() {
    console.log('a1');
    var c = function(b2) { 
        var d = function() { 
            console.log('a2'); 
            b2(); 
        });
        requestAnimationFrame(d);
    }
    b(c);
}

function b(a2) {
    console.log('b1');
    var e = function() { 
        var f = function() { 
            console.log('b2'); 
        });
        requestAnimationFrame(f);
    }
    a2(e);
}

这是相同的代码,除了我已经命名了四个匿名函数cdef,因为我想参考它们。

这是执行的顺序:

  1. a被称为
  2. a同步拨打b
  3. b同步拨打c
  4. c调用requestAnimationFrame(异步API)
  5. requestAnimationFrame返回
  6. c返回
  7. b返回并执行
  8. a返回并完成执行。
  9. 稍后,当动画帧可用时,会发生这种情况:

    1. d被称为
    2. d同步拨打e
    3. e来电requestAnimationFrame
    4. 当然,e可以访问b中定义的变量,这些变量比原始b的执行更长,这要归功于JavaScript闭包。

      同样,在JavaScript中,我们将a视为异步操作,一旦所有a启动完成就结束,但是其中只有两个异步步骤(4和11),所以那两个将受益于承诺。

      现在回答你的问题:承诺可以提供相同的结果和分离,而不知道一个?是的,但它不能与您的示例进行公平的比较,因为它会在您的同步调用不需要时将其同步为异步:

      function a() {
          console.log('a1');
          var b2;
          b().then(function(result) {
              b2 = result;
              return new Promise(function(r) { requestAnimationFrame(r); })
          }).then(function() { 
              console.log('a2'); 
              return b2();
          }).catch(function(e) {
              console.log(e.message); // error-handling
          });
      }
      
      function b() {
          console.log('b1');
          return Promise.resolve(function() {
              return new Promise(function(r) {
                  requestAnimationFrame(r);
              }).then(function() { 
                  console.log('b2'); 
              });
          });
      }
      

      这里的技巧是b返回稍后在a中执行的步骤,这是一个可以重复的模式。

      这是一个好模式吗?很难说在不了解原始用例的情况下。对于异步调用,我还没有遇到一个没有从承诺中受益的调用,但对于同步调用我不会,因为它会改变执行顺序(除非可能只有一个异常值,所有其余的是异步的,它有助于提高可读性。)