我有一个循环,我需要在回调中运行,不幸的是,在回调之外访问数组会留下一个空白数组。我知道为什么会这样,但我想知道解决这个问题的最佳解决方案。
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 */
});
});
};
答案 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] */ });