Node.js 推送到回调函数内循环内的数组

Node.js 推送到回调函数内循环内的数组,node.js,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', fun

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

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  */
    });
});
};
Gallery.prototype.getGallery=函数(cb){
self=这个;
var cos=new pb.CustomObjectService();
var ms=new pb.MediaService();
var s=[];
cos.loadTypeByName('Gallery Image',函数(err,Gallery){
cos.findByType(gallery.\u id.toString(),函数(err,rpy){
对于(变量i=0;iconsole.log(r.location);/*将
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的调用封装在promise中。下面是你自己的版本,但通常称为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(rpy.map(loadByIdPromise))
    .then(function(data) {
        // comes here when all individual async calls complete successfully
        // data is your array of results
    });
使用Promissions样式,您的整个代码如下所示:

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] */ });

我不是向下投票人,但这个问题已经被问了几十次了。为什么你会认为数组会在异步调用完成之前被填充?回调是异步执行的——这意味着“将来的某个时候”。除非你有一台时间机器,否则你无法访问在将来某个时候才会设置的变量。感谢torazaburo,正如我所说,我知道为什么……问题是解决这个问题的最优雅的方法是什么。