此代码中嵌套承诺的目的是什么?

时间:2015-01-29 15:27:05

标签: javascript promise bluebird

我正在努力熟悉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;

代码。如果已经确定了针,那么将它嵌套在另一个承诺中的目的是什么?

2 个答案:

答案 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中的地图更改行为要快得多,但不能保证排队顺序)。