我正在努力熟悉Promises及其工作原理。虽然这对我来说是一个新概念,但我相信我能理解其中的大部分内容。特别是我一直在查看BlueBird库,并通过示例进行操作。但是,页面上有一个代码片段,我无法完全理解。
Promise.promisifyAll(needle);
var options = {};
var current = Promise.resolve();
Promise.map(URLs, function(URL) {
current = current.then(function () {
return needle.getAsync(URL, options);
});
return current;
}).map(function(responseAndBody){
return JSON.parse(responseAndBody[1]);
}).then(function (results) {
return processAndSaveAllInDB(results);
}).then(function(){
console.log('All Needle requests saved');
}).catch(function (e) {
console.log(e);
});
在此代码中,我了解needle
库正在被宣传。我认为我说current
被设定为空洞的承诺是正确的。
我的问题围绕着
current = current.then(function () {
return needle.getAsync(URL, options);
});
return current;
代码。如果已经确定了针,那么将它嵌套在另一个承诺中的目的是什么?
答案 0 :(得分:1)
这是一种排队异步调用的可疑方式,同时将它们放到map
函数中,以便生成所有结果数组的承诺。
那它是做什么用的?单独排队通常是done using reduce
,与current
累加器的循环也是一样的。它以空承诺开始,并重复链接数组中每个url的回调;像这样的代码:
var current = Promise.resolve().then(function() {
return needle.getAsync(URL[0], options);
}).then(function() {
return needle.getAsync(URL[1], options);
}).then(function() {
return needle.getAsync(URL[2], options);
}) …
但是,在map
循环中使用它实际上会生成一个单一承诺的数组,例如
var promises = [];
promises[0] = Promise.resolve().then(function() {
return needle.getAsync(URL[0], options);
});
promises[1] = promises[0].then(function() {
return needle.getAsync(URL[1], options);
});
promises[2] = promises[1].then(function() {
return needle.getAsync(URL[2], options);
});
…
我要使用reduce
方式,从Promise.resolve([])
开始,逐步添加到结果数组,或者写一个专用的scan
(或mapAccum
,无论你想要命名它,都可以与Promise.all
结合使用。
或者更好,只需使用Bluebird的内置{concurrency: 1}
option for Promise.map
!
答案 1 :(得分:1)
Bergi写了一个很好的答案你应该阅读。以下是我使用.each
编写代码的方法:
var get = Promise.promisify(needle.get);
Promise.each(URLs, get). // make the requests
map(function(x){ return JSON.parse(x[1])} ). // parse response as json
then(processAndSaveAllInDB).
then(function(){ console.log("All Needle requests saved"); }).
请注意,您不需要catch
,因为Bluebird会发现未处理的拒绝,并在这种情况下为您举报。
通常,当人们按照上面的代码执行操作时,他们会关心订单,尽管在原始代码中无法保证(蓝鸟2中的地图更改行为要快得多,但不能保证排队顺序)。