NodeJS - 使用Q对一组对象进行异步操作,并进行扭曲

时间:2014-08-18 22:15:46

标签: arrays node.js asynchronous promise q

我也是Q和承诺的新手,并且几天来一直在努力解决这个问题。我正在尝试迭代一个可变长度的RECORDS数组,使用异步调用中每个记录的ID来检索OBJECT(在redis的情况下)。

我需要将RECORD中的一些数据与检索到的OBJECT中的一些数据结合起来,从这些组合对象中创建一个新数组,然后返回。

我的失败代码如下所示:

arrayOfThingRecords = [... an array of small objects, each with a 'thingid'...];
arrayOfCombinedObjects = [];

arrayOfThingRecords.forEach(function(thingRecord) {

    Q.ninvoke(redisClient, "HGETALL", thingRecord.thingid)
    .then((function (thingObject) {
        combinedThingObject = {
            thingStuffFromRecord: thingRecord.thingStuffFromRecord,
            thingStuffFromObject: thingObject.thingStuffFromObject
        };
    }).done(function () {
        arrayOfCombinedObjects.push(combinedThingObject)
    }); //   

}; // Then do stuff with arrayOfThingObjects...

我知道使用forEach是错误的,因为它在promises返回之前执行。我一直在努力与Q.all()Q.settled()合作,并建立一系列承诺等等,但我完全感到困惑,怀疑/希望我可能会比这需要更难是。

1 个答案:

答案 0 :(得分:0)

请勿使用您手动填充的全局arrayOfCombinedObjects = []。始终使用相应操作的结果值来解决您的承诺。例如,

Q.ninvoke(redisClient, "HGETALL", thingRecord.thingid)
.then(function(thingObject) {
    return {
//  ^^^^^^
        thingStuffFromRecord: thingRecord.thingStuffFromRecord,
        thingStuffFromObject: thingObject.thingStuffFromObject
    };
});

成为该对象的承诺

现在,使用Q.all是正确的方法。它需要一个 promises数组,并将它们组合成一个包含所有结果数组的promise。所以我们需要构建一个promises数组 - 一个来自上面的这些对象的promise的数组。您可以使用forEach次迭代和push将数组放在一起,但使用map会更容易。然后变成

var arrayOfThingRecords = [... an array of small objects, each with a 'thingid'...];
var arrayOfPromises = arrayOfThingRecords.map(function(thingRecord) {
    return Q.ninvoke(redisClient, "HGETALL", thingRecord.thingid)
//  ^^^^^^ let the promise be part of the new array
    .then(function(thingObject) {
        return {
            thingStuffFromRecord: thingRecord.thingStuffFromRecord,
            thingStuffFromObject: thingObject.thingStuffFromObject
        };
    });
});
Q.all(arrayOfPromises).then(function(arrayOfCombinedObjects) {
    // Then do stuff with arrayOfThingObjects...
});