NodeJS - 使用 Q 对对象数组执行异步操作,有点扭曲

Posted

技术标签:

【中文标题】NodeJS - 使用 Q 对对象数组执行异步操作,有点扭曲【英文标题】:NodeJS - using Q to do async operations on an array of objects, with a twist 【发布时间】:2014-10-11 22:22:57 【问题描述】:

我也是 Q 和 promises 的新手,并且已经为这个问题苦苦挣扎了好几天。我正在尝试遍历一个可变长度的 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 是错误的,因为它在承诺返回之前执行。我一直在尝试与Q.all()Q.settled() 合作,并建立一系列承诺等,但我完全感到困惑并怀疑/希望我可能会让这变得比需要的更难。

【问题讨论】:

【参考方案1】:

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

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

成为该对象的承诺

现在,使用Q.all 是正确的方法。它需要一个promise 数组,并将它们组合成一个promise,以获得所有结果的数组。所以我们需要构建一个promise数组——一个来自上面的这些对象的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...
);

【讨论】:

谢谢!这完全有道理。我回到“末日金字塔”开始行动,但很快就会用这种方法换掉它。出于某种原因,我发现这个承诺的东西很奇怪。再次感谢! @DavidC.:很高兴能帮上忙。请accept the answer!

以上是关于NodeJS - 使用 Q 对对象数组执行异步操作,有点扭曲的主要内容,如果未能解决你的问题,请参考以下文章

使用 std::atomic<int> 索引对大型数组进行异步并行化操作有多安全

nodejs异步调用async

nodejs 中的异步和 Q 承诺

循环执行 Node JS 中的 fetch 操作

使用异步和请求包(NodeJS / Express)进行多个 API 调用

Nodejs异步执行