使用 ES6 promises 的顺序迭代
Sequential iteration using ES6 promises
我期待下面的 node.js 代码将按以下顺序打印输出
1000
2000
3000
4000
"All tasks completed"
而是按下面提到的顺序打印
"All tasks completed"
1000
2000
3000
4000
代码
'use strict';
var tasks = [1000, 2000, 3000, 4000];
var promise = Promise.resolve();
function test() {
tasks.forEach(function(task) {
promise = promise.then(function() {
setTimeout(function() {
console.log(task);
}, task);
});
});
}
test();
promise.then(function() {
console.log('All tasks completed');
});
需要修改什么,以便"All tasks completed"最后打印。
- 我的示例使用 ES6 promises 而不是 bluebird 。
- 此外,我不是在问关于 promises 的一般性问题,而是关于一个具体的例子。
在所有 then
函数中,您没有 returning 任何东西,而是触发异步操作。因此,promise 链与异步操作无关。这就是为什么您无法按照自己的意愿控制流量。
你可以做的是,return 来自每个 then
处理程序的 Promise,只有在异步操作完成时才会解决,就像这样
tasks.forEach(function(task) {
promise = promise.then(function() {
return new Promise((resolve, reject) => {
setTimeout(function() {
console.log(task);
resolve();
}, task);
})
});
});
记住,这将一个接一个地触发异步操作。例如,一秒钟后,它将打印 1000,然后将启动第二个异步操作,等待两秒钟,然后打印 2000,依此类推。基本上,您的程序将在大约 10 秒(1 + 2 + 3 + 4 秒)后退出,因为我们正在按顺序执行所有异步函数。
但是如果你想让它们全部同时触发,那么使用Promise.all
,像这样
'use strict';
var tasks = [1000, 2000, 3000, 4000];
function test() {
return Promise.all(tasks.map(function(task) {
return new Promise((resolve, reject) => {
setTimeout(function() {
console.log(task);
resolve();
}, task);
})
}));
}
test().then(function() {
console.log('All tasks completed');
});
现在,所有的异步函数都是一次性触发的,所以一秒后打印1000,两秒后打印2000等等。您的程序将在 4 秒后完成所有异步操作,因为它们都是立即启动的。
目前,这是我想出的以顺序和阻塞方式迭代 promise 数组的唯一方法...
请检查代码示例...
const list = [1,2,3,4,5];
数字越大,承诺得到解决的速度就越快
const functionWithPromise = item => {
return new Promise((resolve) =>{
setTimeout(resolve, 6000 - (1000 * item ) , item);
})}
Promise.all returns 一个包含 promises 的数组
const getData = async () => Promise.all(await iterateSequentiallyPromiseArray(list,functionWithPromise));
for 循环是唯一以阻塞方式迭代的循环
const iterateSequentiallyPromiseArray = async (array, fn) => {
try {
const results = [];
for (let i = 0; i < array.length; i++) {
console.log('Start with index: ', i);
const r = await fn(array[i]);
console.log('in promise iteration', r);
results.push(r);
}
return results; // will be resolved value of promise
} catch (err) {
console.log('_processArray');
throw err;
}
};
启动链
getData().then(console.log);
我期待下面的 node.js 代码将按以下顺序打印输出
1000
2000
3000
4000
"All tasks completed"
而是按下面提到的顺序打印
"All tasks completed"
1000
2000
3000
4000
代码
'use strict';
var tasks = [1000, 2000, 3000, 4000];
var promise = Promise.resolve();
function test() {
tasks.forEach(function(task) {
promise = promise.then(function() {
setTimeout(function() {
console.log(task);
}, task);
});
});
}
test();
promise.then(function() {
console.log('All tasks completed');
});
需要修改什么,以便"All tasks completed"最后打印。
- 我的示例使用 ES6 promises 而不是 bluebird 。
- 此外,我不是在问关于 promises 的一般性问题,而是关于一个具体的例子。
在所有 then
函数中,您没有 returning 任何东西,而是触发异步操作。因此,promise 链与异步操作无关。这就是为什么您无法按照自己的意愿控制流量。
你可以做的是,return 来自每个 then
处理程序的 Promise,只有在异步操作完成时才会解决,就像这样
tasks.forEach(function(task) {
promise = promise.then(function() {
return new Promise((resolve, reject) => {
setTimeout(function() {
console.log(task);
resolve();
}, task);
})
});
});
记住,这将一个接一个地触发异步操作。例如,一秒钟后,它将打印 1000,然后将启动第二个异步操作,等待两秒钟,然后打印 2000,依此类推。基本上,您的程序将在大约 10 秒(1 + 2 + 3 + 4 秒)后退出,因为我们正在按顺序执行所有异步函数。
但是如果你想让它们全部同时触发,那么使用Promise.all
,像这样
'use strict';
var tasks = [1000, 2000, 3000, 4000];
function test() {
return Promise.all(tasks.map(function(task) {
return new Promise((resolve, reject) => {
setTimeout(function() {
console.log(task);
resolve();
}, task);
})
}));
}
test().then(function() {
console.log('All tasks completed');
});
现在,所有的异步函数都是一次性触发的,所以一秒后打印1000,两秒后打印2000等等。您的程序将在 4 秒后完成所有异步操作,因为它们都是立即启动的。
目前,这是我想出的以顺序和阻塞方式迭代 promise 数组的唯一方法...
请检查代码示例...
const list = [1,2,3,4,5];
数字越大,承诺得到解决的速度就越快
const functionWithPromise = item => {
return new Promise((resolve) =>{
setTimeout(resolve, 6000 - (1000 * item ) , item);
})}
Promise.all returns 一个包含 promises 的数组
const getData = async () => Promise.all(await iterateSequentiallyPromiseArray(list,functionWithPromise));
for 循环是唯一以阻塞方式迭代的循环
const iterateSequentiallyPromiseArray = async (array, fn) => {
try {
const results = [];
for (let i = 0; i < array.length; i++) {
console.log('Start with index: ', i);
const r = await fn(array[i]);
console.log('in promise iteration', r);
results.push(r);
}
return results; // will be resolved value of promise
} catch (err) {
console.log('_processArray');
throw err;
}
};
启动链
getData().then(console.log);