这两种处理顺序Promise的方式有什么区别?

3
当我们想要按顺序依次执行多个then函数时,以下两种方式有何不同:
1- 使用嵌套的thens
$http.get('api').then(function(){
    processBlocks(obj.data).then(function(){
        alert('it is done')
    });
});

2- 将嵌套的then语句展开

$http.get('api').then(function(){
    return processBlocks(obj.data);
}).then(function(){
    alert('it is done')
});

很明显第二个更易读,但它的性能是否有差异呢?

1
值得一提的是,Angular现在使用Observables而不是Promises来处理HTTP请求,这有其自己的惯用编码风格。 - Dai
区别在于第二个是正确的,而第一个不是。 - Madara's Ghost
2个回答

3
$http.get('api').then(function(){
    processBlocks(obj.data).then(function(){
        alert('it is done')
    });
});

在这种情况下,如果您像下面这样连接另一个then
$http.get('api').then(function(){
    processBlocks(obj.data).then(function(){
        alert('it is done')
    });
}).then(function(){
alert('it is done')
});

如果processBlocks()抛出异常,那么不用担心,下一个 Promise 仍将被触发。但是:
$http.get('api').then(function(){
    return processBlocks(obj.data);
}).then(function(){
    alert('it is done')
});

在这种情况下,如果第一个then失败,那么该序列将被取消,如果有catch块,则会触发它。

1
比这更糟糕的是,你永远无法在第一个示例中进一步等待内部 Promise。如果在外部添加 .then()(因为那是返回的 Promise),它将不会等待内部 Promise 的完成,只会等待外部 Promise,因为你没有返回一个 Promise。 - Madara's Ghost

1

可能会有一点点性能差异,因为传递给.then的函数与初始链接的Promise一起链接时,解释器在该行上遇到初始Promise时会链式运行该函数。举个例子,当所有Promises以平坦的方式链接在一起时,第二个链接的expensiveFunctionThatReturnsFunc()会立即运行,以创建要放入.then链中的函数:

const resolveAfter = ms => new Promise(res => setTimeout(res, ms));

const expensiveFunctionThatReturnsFunc = () => {
  console.log('making fn...');
  // for (let i = 0; i < 999999999; i++) {}
  return () => console.log('resolving');
}

console.log('start');
resolveAfter(1000)
  .then(() => resolveAfter(1000))
  .then(expensiveFunctionThatReturnsFunc());

相比之下,当您有嵌套的 then 时,只有在第一个 Promise 解决后,expensiveFunctionThatReturnsFunc() 才会运行一次:

const resolveAfter = ms => new Promise(res => setTimeout(res, ms));

const expensiveFunctionThatReturnsFunc = () => {
  console.log('making fn...');
  // for (let i = 0; i < 999999999; i++) {}
  return () => console.log('resolving');
}

console.log('start');
resolveAfter(1000)
  .then(() => {
    return resolveAfter(1000)
    .then(expensiveFunctionThatReturnsFunc());
  });

然而,在99%的情况下,这种事情的影响完全是无法察觉的。不用担心它,最好只是让你的代码易读。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接