推送到回调函数内部循环内的数组

时间:2015-02-12 00:41:40

标签: node.js

我有一个循环,我需要在回调中运行,不幸的是,在回调之外访问数组会留下一个空白数组。我知道为什么会这样,但我想知道解决这个问题的最佳解决方案。

Gallery.prototype.getGallery = function(cb) {
self = this;
var cos = new pb.CustomObjectService();
var ms = new pb.MediaService();

var s = [];

cos.loadTypeByName('Gallery Image', function(err, gallery){

    cos.findByType(gallery._id.toString(), function(err, rpy){

        for(var i = 0; i < rpy.length; i++){
            ms.loadById(rpy[i].Image, function(e,r){
                s.push(r.location);
                console.log(r.location); /* <-- logs expected data */
            });     
       }
       console.log(s[0]); /* <-- this is undefined  */
    });
});
};

1 个答案:

答案 0 :(得分:0)

通过调用for替换您的async.*循环;在这种情况下,async.map似乎是正确的。将回调传递给async.map;当完成对ms.loadById的所有单独调用时,将使用结果数组调用它。

async.map(
    rpy, 
    function(elt, callback) {
        ms.loadById(elt.Image, callback);
    },
    function(err, data) {
        // comes here after all individual async calls have completed
        // check errors; array of results is in data
    }
);

如果你想进入promises世界,那么在一个承诺中包含对ms.loadById的调用。这是一个自己动手的版本,但通常称为promisify的各种版本也在那里。

function loadByIdPromise(elt) {
    return new Promise(function(resolve, reject) {
        ms.loadById(elt.image, function(err, data) {
            if (err) return reject(err);
            resolve(data);
        });
    });
}

然后对所得到的承诺进行Promise.all

Promise.all(rpy.map(loadByIdPromise))
    .then(function(data) {
        // comes here when all individual async calls complete successfully
        // data is your array of results
    });

使用promises样式,您的整个代码如下所示:

loadTypeByNamePromise('Gallery Image') .
    then(function(gallery) { return findByTypePromise(gallery._id.toString(); }) . 
    then(function(rpy)     { return Promise.all(rpy.map(loadByIdPromise)); }) .
    then(function(results) { /* do something with [results] */ });