首页 文章

在Bluebird的承诺链中将同步函数转换为异步的原因是什么?

提问于
浏览
2

Bluebird的文档和外部帖子提到了异步错误和同步错误之间的差异,并且有一些函数可以帮助将所有这些错误归结为异步错误(例如, Promise.tryPromise.method )?这似乎是因为(除其他事项外)错误处理对于两者来说是不同的(同步是用 try / catch 捕获的,而异步是用 .catch 捕获的) .

但是,在一系列链式函数的第一个方法之后, then 语句是否接受同步函数( throws 被视为拒绝, return 作为解析)或承诺(使用标准 reject / resolve )? (例如,在a() . 然后(b).then(c).catch(function(e){}) - b / c部分) . 最终 .catch 似乎从promise中的拒绝或同步代码中的throw中收集错误 .

那么这些额外的Bluebird函数的主要目的仅在于回调链的第一部分吗?或者是否有其他原因将同步代码转换为承诺 .

1 回答

  • 0

    让我们看一个非常基本的例子,我们在某段代码中有异步和同步路径:

    var expiryTime = 1457155658238;
    var cachedCopy = 'abcdefghijk';
    
    var p = Date.now() > expiryDate ? getNewCopy() : cachedCopy;
    
    p.then(function (information) {
      // do something
    });
    

    请注意这里的问题?由于 cachedCopy 不是一个promise,如果条件沿着这条路径行进,它将抛出一个错误 . 因此,我们需要将 cachedCopy 包装成一个承诺:

    var p = Date.now() > expiryDate ? getNewCopy() : Promise.resolve(cachedCopy);
    

    但是,如果我们必须为多个代码路径执行此操作,这可能会变得乏味 . 您可能想知道为什么我们不是简单地将它放入函数中然后在返回值上调用 Promise.resolve 以将其包装到promise中 . 拿这个代码:

    var expiryTime = 1457155658238;
    var cachedCopy = 'abcdefghijk';
    var canGetNewCopy = false;
    
    function getInfo() {
      if (Date.now() < expiryDate) return cachedCopy;
      if (canGetNewCopy) return getNewCopy();
      throw new Error('fail!');
    }
    
    Promise.resolve(getInfo()).then(function (information) {
      // do something
    }).catch(function (error) {
      console.log('an error occured!');
      cleanup();
    });
    

    如果超过到期日会怎样?因为 getInfo() 将抛出错误,清理代码将不会运行 .

    Bluebird的 Promise.try 解决了所有这些问题 . 通过捕获传递的函数内部抛出的错误,以及在同步返回的情况下将值包装到promise中,这可以节省大量代码包装并减少代码中细微错误的可能性 . 现在我们的示例看起来像这样:

    var expiryTime = 1457155658238;
    var cachedCopy = 'abcdefghijk';
    var canGetNewCopy = false;
    
    Promise.try(function () {
      if (Date.now() < expiryDate) return cachedCopy;
      if (canGetNewCopy) return getNewCopy();
      throw new Error('fail!');
    }).then(function (information) {
      // do something
    }).catch(function (error) {
      console.log('an error occured!');
      cleanup();
    });
    

    现在,如果在 Promise.try 回调中抛出错误,则返回的promise将被拒绝,因此清理代码将运行 . 由于类似的原因,Bluebird中也存在 Promise.method (以确保API中的函数始终返回一个promise) .

相关问题