序
在异步方法执行后再执行的直接解决方案就是写回调。
可是如果想让所有的(例如循环调用的若干次)异步方法全部执行完之后再执行接下来的方法该怎么办呢?
本文基于Promise语法,给出解决方案。
接着上一篇的例子,我们先来看一下有问题的写法。
有问题的写法:
-
var request =
require(
'request');
-
-
// 异步获取网络资源的方法
-
getWeb =
(index, getCallback) => {
-
var url =
'http://www.duzixi.com';
-
-
request(url,
function (error, response, body) {
-
if (!error && response.statusCode ==
200)
-
{
-
getCallback(body);
-
return body;
-
-
}
else {
-
console.log(response.statusCode +
" " + error);
-
getCallback(
"");
-
return
"";
-
}
-
})
-
}
-
-
// 循环调用
-
for (
var i =
0; i <=
10; i++) {
-
(
(index)=>{
-
getWeb(index, (body)=>{
-
console.log(index);
-
})
-
})(i)
-
}
-
-
console.log(
"All done!");
神奇的运行结果:
All done!
1
2
3
0
4
6
5
7
9
8
10
源代码最后输出的All done! 居然出现在了最上面。
原因相比不用多说大家也知道,由于异步方法是花费时间的,所以输出事件后发生。
问题的解决方案:
这个问题的解决方案就是Promise,循环调用部分的源代码修改如下:
var actions = []; // 定义一个空的方法数组
-
// 循环调用
-
for (
var i =
0; i <=
10; i++) {
-
var action =
() => {
// 将每一次循环方法定义为一个方法变量
-
return
new
Promise(
resolve =>{
// 每个方法返回一个Promise对象,第一个参数为resolve方法
-
(
(index)=>{
-
getWeb(index, (body)=>{
-
console.log(index);
-
resolve();
// 在方法结束时调用resolve()方法
-
})
-
})(i)
-
-
})
-
}
-
actions.push(action());
// 将每次循环调用的方法添加到方法数组中
-
}
-
-
Promise.all(actions).then(
()=>{
// 调用Promise的all方法,传入方法数组,结束后执行then方法参数中的方法
-
console.log(
"All done!");
-
});
最终的运行结果:
8
7
5
9
4
1
10
6
2
3
0
All done!
最后,感谢小红帮助解答了该问题。
注:本文转自Node.js的那些坑,作者:莲兮奈若何