Joh*_*ell 7 javascript asynchronous node.js promise bluebird
我正在寻找蓝鸟的一些任务,只是使用超时作为实验机制.[不希望使用异步或任何其他库]
var Promise = require('bluebird');
var fileA = {
1: 'one',
2: 'two',
3: 'three',
4: 'four',
5: 'five'
};
function calculate(key) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(fileA[key]);
}, 500);
});
}
Promise.map(Object.keys(fileA), function (key) {
calculate(key).then(function (res) {
console.log(res);
});
}).then(function () {
console.log('finish');
});
Run Code Online (Sandbox Code Playgroud)
结果是
finish,
one,
two,
three,
four,
five,
Run Code Online (Sandbox Code Playgroud)
我需要循环只在每个超时完成后迭代一次,然后用完成后触发最后一个.
the*_*eye 15
在传递给的函数对象中Promise.map,需要返回一个Promise对象,以便解析所有的Promises,并将已解析的值数组传递给下一个then函数.在您的情况下,由于您没有明确地返回任何内容,undefined因此默认情况下将返回,而不是承诺.因此,使用s 解析了finish作为Promises执行的可执行函数.你可以这样确认Promises.mapundefined
...
}).then(function (result) {
console.log(result);
console.log('finish');
});
Run Code Online (Sandbox Code Playgroud)
会打印
[ undefined, undefined, undefined, undefined, undefined ]
finish
one
two
three
four
five
Run Code Online (Sandbox Code Playgroud)
所以,你的代码应该有这样的return声明
Promise.map(Object.keys(fileA), function (key) {
return calculate(key).then(function (res) {
console.log(res);
});
}).then(function () {
console.log('finish');
});
Run Code Online (Sandbox Code Playgroud)
现在,您将看到代码按顺序打印事物,因为我们返回Promise对象,并且在解析了finish所有Promise 之后调用thenable函数.但它们都没有顺序解决.如果发生这种情况,将在指定的时间过后打印每个数字.这将我们带到第二部分.
Promise.map只要解析了数组中的Promises,就会执行作为参数传递的函数.引用文档,
尽可能快地调用给定项的映射器函数,也就是说,当满足输入数组中该项的索引的承诺时.
因此,数组中的所有值都将转换为Promises,并使用相应的值进行解析,并且将立即为每个值调用该函数.所以,他们都在同一时间等待500毫秒并立即解决.这不会顺序发生.
由于您希望它们按顺序执行,因此您需要使用Promise.each.引用文档,
迭代按顺序发生.....如果迭代器函数返回promise或者thenable,则在继续下一次迭代之前等待promise的结果.
由于Promises是连续创建的并且在继续之前等待分辨率,因此保证了结果的顺序.所以你的代码应该成为
Promise.each(Object.keys(fileA), function (key) {
return calculate(key).then(function (res) {
console.log(res);
});
}).then(function () {
console.log('finish');
});
Run Code Online (Sandbox Code Playgroud)
附加说明:
如果命令无关紧要,正如Benjamin Gruenbaum所建议的那样,你可以使用Promise.map自己的concurrency限制,就像这样
Promise.map(Object.keys(fileA), function (key) {
return calculate(key).then(function (res) {
console.log(res);
});
}, { concurrency: 1 }).then(function () {
console.log('finish');
});
Run Code Online (Sandbox Code Playgroud)
该concurrency选项基本上限制了在创建更多承诺之前可以创建和解决的Promises数量.因此,在这种情况下,由于限制为1,它将创建第一个承诺,并且当达到限制时,它将等到创建的Promise结算,然后转到下一个Promise.
如果整个使用点calculate是引入延迟,那么我会建议Promise.delay,可以像这样使用
Promise.each(Object.keys(fileA), function (key) {
return Promise.delay(500).then(function () {
console.log(fileA[key]);
});
}).then(function () {
console.log('finish');
});
Run Code Online (Sandbox Code Playgroud)
delay 可以透明地将Promise的已解析值链接到下一个可执行的函数,因此代码可以缩短为
Promise.each(Object.keys(fileA), function (key) {
return Promise.resolve(fileA[key]).delay(500).then(console.log);
}).then(function () {
console.log('finish');
});
Run Code Online (Sandbox Code Playgroud)
由于Promise.delay接受动态值,您可以简单地写为
Promise.each(Object.keys(fileA), function (key) {
return Promise.delay(fileA[key], 500).then(console.log);
}).then(function () {
console.log('finish');
});
Run Code Online (Sandbox Code Playgroud)
如果Promise链在这里结束,那么最好使用.done()方法来标记它,就像这样
...
}).done(function () {
console.log('finish');
});
Run Code Online (Sandbox Code Playgroud)
一般注意:如果您不打算在一个可执行的功能中进行任何处理,但是您只是为了跟踪进度或跟踪该过程,那么您可以更好地将它们更改为Promise.tap.所以,你的代码就会变成
Promise.each(Object.keys(fileA), function (key) {
return Promise.delay(fileA[key], 500).tap(console.log);
}).then(function () {
// Do processing
console.log('finish');
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3526 次 |
| 最近记录: |