求教,如何使用 promise 完成循环状态下的链式异步任务

2017-04-07 17:59:15 +08:00
 abcbuzhiming
Promise 能像下面这样顺序完成链式异步任务

promise1().then(function(data) {
console.log(data);
return promise2();
})
.then(function(data) {
console.log(data);
return promise3();
})
.then(function(data) {
console.log(data);
return '结束了吧'
}).then(function(data) {
console.log(data);
});
}
但是这里存在一个问题, promise2 和 promise3 都必须是在外部预定义好的。

但是现在我有这么一个需求,我可能有一大批 promise 对象,这些 promise 对象都是按一定算法用循环生成的。结果这就遇到了坑,我试图这么干

function axiosLoop(index) {
/*
XXXXXX
*/
return axiosObj;
}
var objTemp = null;
for (var i = 0; i < 10; i++) {
objTemp = axiosLoop(i).then(function (data) {
console.log(data);
return axiosLoop(i+1); //这么干是不行的,因为这个 i 值是引用外部的 i ,它会直接演变成最大的 10
}).catch(function (error) {
console.log(error);
});
}

=========
我该怎么解决这个问题,这个问题不能使用类似 promis.all()来执行,因为我一定要保证有序执行
6644 次点击
所在节点    JavaScript
13 条回复
freeminder
2017-04-07 18:24:12 +08:00
再包一层
objTemp = axiosLoop(i).then((function (idx){
return function(data){
console.log(data);
return axiosLoop(idx);
}
})(i+1)).catch(function (error) {
console.log(error);
});
nino
2017-04-07 18:43:50 +08:00
AlisaDestiny
2017-04-07 18:56:27 +08:00
@freeminder 跟我第一感一样。用闭包。
bdbai
2017-04-07 21:52:20 +08:00
支持 ES6 的话,把 for 里面的 var 改成 let 。
hythyt9898
2017-04-07 22:06:32 +08:00
为何不用 async/await ?
ck65
2017-04-07 23:19:01 +08:00
比较脏难维护和扩展,但能解燃眉之急的方案:引 deasync 包,把请求封装成一个同步方法。
需要额外学习、要求特定 nodejs 版本或使用编译工具,但优雅稳定的方案: async/await 。
abcbuzhiming
2017-04-07 23:30:40 +08:00
@freeminder
@AlisaDestiny
@ck65
谢谢楼上各位,奋斗了一晚上,终于在重新理解 promise 模型和闭包变量作用域的基础上,按照 freeminder 的方法搞定了。折腾死了,我终于明白为啥 Promise 仅仅出来了两年就被 async/await 干掉了, 12 万分的希望 async/await 早日在前端普及吧,再也不想拿 Promise 写东西了
spritevan
2017-04-08 01:10:35 +08:00
imdoge
2017-04-08 01:34:52 +08:00
可以用 reduce 来, arr.reduce((promise, item) => { return promise.then(() => asyncReq(item)), asyncReq1()}
xieranmaya
2017-04-08 12:31:57 +08:00
[p1,p2,p3].reduce((seq,next) => seq.then(value=>next()), Promise.resolve())

说白了有点像 x = x + n
你看啊: seq = seq.then(value => task(value)
是不是很像
bdbai
2017-04-08 22:00:58 +08:00
@abcbuzhiming Promise 活的好好的,没被干掉吧。
嫌原生 Promise 不好用可以试试 bluebird 。
xieranmaya
2017-04-09 12:49:30 +08:00
@abcbuzhiming
@bdbai 说的很对, Promise 并没有“被” async/await 干掉,相反, async/await 是基于 Promise 的,如果你不深入理解 Promise ,你也不会真正理解 async/await ,事实上, async 函数的调用就是返回 Promise ,而 await 操作符后面必须是一个 Promise 对象,这意味着你要用 async/await 的时候,必须还是要自己实现一些返回 Promise 的函数
LeoEatle
2017-04-09 14:31:53 +08:00
最简单的处理方案就是,用 let

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/353282

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX