承诺嵌套vs链式

时间:2017-04-18 02:20:58

标签: javascript scope promise

承诺的新事物;考虑promiseA()promiseB(a)取决于第一个结果的情况,我想从两者中收集结果并执行第三个操作doSomething(a, b)

样式A(闭包/嵌套)

promiseA().then(function (resultA) {
  return (promiseB(resultA).then(function (resultB) {
    doSomething(resultA, resultB);
  }));
});

样式B(返回值/链接)

promiseA().then(function (resultA) {
  return Promise.all([resultA, promiseB(resultA)]);
}).spread(function (resultA, resultB) {
  doSomething(resultA, resultB);
});

据我所知,这些是等价的:

  • promiseApromiseB
  • 之间的相同排序约束
  • 最终承诺返回undefined
  • 如果promiseApromiseB被拒绝或doSomething被拒绝,最终承诺将被拒绝。

作为风格问题,风格B减少了缩进(厄运的金字塔)。

然而,风格B更难以重构。如果我需要引入中间版promiseA2(a)doSomething(a, a2, b),我需要修改3行(Promise.allspreaddoSomething),这可能会导致错误(意外交换等),而Style AI只修改1行(doSomething),变量名称清楚表明它是什么结果。在大型项目中,这可能很重要。

两种风格之间是否存在其他非功能性权衡?一个与另一个的内存分配更多/更少?事件循环周围有更多/更少的转弯?异常的堆栈跟踪更好/更差?

1 个答案:

答案 0 :(得分:0)

我认为这两种方法之间的非功能性权衡并不那么重要:第二种方法在创建数组时会有一些开销,并传播相应的结果,并且会产生一个更多的承诺。但是在异步流程中,我认为这一切都可以忽略不计。

您主要担心的是重构的难易程度。

为此,我建议使用一组函数,并Model.where(id: params[:id_list]).destroy_all 覆盖它:

reduce

这个想法是[promiseA, promiseB, doSomething].reduce( (prom, f) => prom.then( (res = []) => ( f(...res) || prom).then( [].concat.bind(res) ) ) , Promise.resolve() ); // Sample functions function wait(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function promiseA() { console.log('promiseA()'); return wait(500).then(_ => 13); } function promiseB(a) { console.log('promiseB(' + a + ')'); return wait(500).then(_ => a + 2); } function doSomething(a, b) { console.log('doSomething(' + a + ',' + b + ')'); }回调链中的下一个函数将所有先前的结果作为参数传递。因此,如果要在链中注入一个promise-returns函数,则需要将其插入到数组中。不过,您需要注意传递的参数:它们在此解决方案中是累积的,因此then不是规则的例外。

如果另一方面,您只希望doSomething获得所有结果,并且只将最新结果传递给每个中间函数,那么代码将如下所示:

doSomething