【问题标题】:promise and collection of loops承诺和循环集合
【发布时间】:2014-03-11 15:42:10
【问题描述】:

请帮助我了解我的代码有什么问题。

所以我要做的是调用异步调用来获取计数。我已经把它变成了一个承诺。

function getCount(client) {
    var xml = "<urn:mgmtISCSIGetTargetList> </urn:mgmtISCSIGetTargetList>";
    client.MgmtServer.MgmtServer.mgmtISCSIGetTargetList(xml, function (err, result) {

        if (err) {
            logger.error(err);
            debug(err);
            return deferred.reject(err);
        }
            deferred.resolve(parseInt(result.list.targetCount));
        }
    });

    return deferred.promise;
};

一旦我使用上述承诺获得计数,我需要进行更多的异步调用,与第一个承诺的返回一样多。

假设稍后执行的代码是另一个承诺。 该代码是:

function az(client, index) {
  var xml = "<urn:mgmtISCSIGetTargetList> </urn:mgmtISCSIGetTargetList>";
    client.MgmtServer.MgmtServer.mgmtISCSIGetTargetList(xml, function (err, result) {

            if (err) {
                return deferred.reject(err);
            }

            var i;
            for (i = 0; i < index; i++) {
                if (1 === i) {
                    console.log('index 1 is bad news');
                    return deferred.reject("Blew up");
                }
            }

            console.log('after the loop');
            deferred.resolve(index);
        }
    );
    return deferred.promise;
};

仅出于测试目的,我对 1 的索引进行了硬编码,拒绝了承诺。 当我把承诺放在一起时,我没有看到我所期望的。 代码是:

getCount(client).then(
    function (count) {
        return az(client, count).then(console.log);
    }
).catch(
    function (err) {
        console.log('caught an error from outer promise');
        console.log(err);
    }
);

我得到的输出是:

3 which is from deferred.resolve(index);
index 1 is bad news which is hard coded failure.

我知道这是一篇很长的帖子,但是有人知道我将这两个承诺链接在一起做错了什么吗?

我将 az 改为:

function az(client, index) {
    var xml = "<urn:mgmtISCSIGetTargetList> </urn:mgmtISCSIGetTargetList>";
    client.MgmtServer.MgmtServer.mgmtISCSIGetTargetList(xml, function (err, result) {

            if (err) {
                return deferred.reject(err);
            }

            if (1 === index) {
                console.log('index 1 is bad news');
                return deferred.reject("Blew up");
            }

            console.log('after the loop with index ' + index);
            deferred.resolve(index + 30);
        }
    );
    return deferred.promise;
};

【问题讨论】:

  • 你在哪里构造deferred变量?
  • 你使用的是什么 promise 库?
  • var defered = require('Q).deferred 我使用 Q 包和 deferred
  • 您期望的输出是什么?什么不起作用?

标签: javascript node.js asynchronous promise q


【解决方案1】:

您只能解决(履行/拒绝)一个承诺一次。在循环中包含 return deferred.reject("Blew up"); 看起来很像设计气味或错误理解。

我需要进行更多的异步调用,与第一个承诺的返回一样多。假设做后者的代码是另一个承诺

每个异步任务都应该有自己的承诺。我对那个描述的期望是

getCount(client).then(function (count) {
    for (var i=0; i<count; i++)
        az(client, i).then(console.log);
})

现在每个az 调用都会返回一个promise,因此您将拥有一个并行执行的promise 数组。如果你需要等待所有的人一起继续他们的所有结果,你需要将它们组合成一个新的承诺。 Q 库确实有一个帮助函数,名为Q.all。你可以这样使用它:

getCount(client).then(function (count) {
    var promises = [];
    for (var i=0; i<count; i++)
        promises.push(az(client, i));
    return Q.all(promises);
}).then(function(results) {
    console.log("everything went right. All results:", results);
}, function(err) {
    console.log("something (either getCount, or one of the az calls) blew up", err);
});

【讨论】:

  • 我想要做的是,如果循环中的任何项目有抛出问题和异常。 deferred.reject 不是正确的方法吗?
  • 是的,但您似乎放错了循环。还是mgmtISCSIGetTargetList 方法一次返回所有项目,您甚至不需要多次调用它?
  • 我放错了循环。必须。 mgmtISCSIGetTargetList 一次返回一项
  • 很高兴听到我的猜测是对的 :-) 那么当 az() 确实为单个值产生承诺时,它是否有效?
  • 不,它没有……这就是我现在所拥有的。我按原样使用您为数组提交的代码,并将 az 更改为读取:正如我在上面添加的那样,我看到了输出:一切正常。所有结果: [ 3, 3, 3 ] 在索引为 0 的循环之后 索引 1 是坏消息,在索引为 2 的循环后出现乱序,并且永远不会看到“出现问题的错误。我将添加我拥有的 az 代码.
猜你喜欢
  • 2021-09-07
  • 2018-12-31
  • 2017-12-18
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 2020-08-16
  • 2019-06-17
  • 2015-12-18
相关资源
最近更新 更多