我正在编写一个函数(由express.js路由调用)来将数据库中的事件信息与其Facebook对应项合并,并将其作为事件对象数组返回。
我遇到了node.js异步性质和解决foreach循环内可变数量的promise之前返回整个对象的问题。我已经尝试过许多不同的代码重组方法(回调,计数器,promise等),但我还没有成功解决这个问题,我真的很想知道为什么。我怀疑这与在foreach循环中变量被覆盖有关,但我不确定如何解决这个问题。
我需要三件事情:
1.我缺少哪些概念上的理解来解决这个问题? 2.我将来如何找到或调试这个问题? 3.如何修复我的代码以使其正常工作?
以下是我的函数:
我遇到了node.js异步性质和解决foreach循环内可变数量的promise之前返回整个对象的问题。我已经尝试过许多不同的代码重组方法(回调,计数器,promise等),但我还没有成功解决这个问题,我真的很想知道为什么。我怀疑这与在foreach循环中变量被覆盖有关,但我不确定如何解决这个问题。
我需要三件事情:
1.我缺少哪些概念上的理解来解决这个问题? 2.我将来如何找到或调试这个问题? 3.如何修复我的代码以使其正常工作?
以下是我的函数:
function mergeEvents(req, res, next, events){
console.log("Merge Events");
var dfd = q.defer();
ensureAuthenticated(req, res, next).then(function(auth){
var iEvent, event;
var promises = [];
if (auth){
console.log("authenticated!");
console.log("auth token: " + ACCESS_TOKEN);
for (iEvent in events){
event = events[iEvent];
var promise = q.defer();
promises.push(promise);
https.get('https://graph.facebook.com/' + event.fb_id + '?access_token=' + ACCESS_TOKEN, function(response) {
var str = '';
response.on('data', function(chunk){
str += chunk;
});
response.on('end', function(){
var fb_event = JSON.parse(str);
event.dataValues.fb = fb_event;
promise.resolve(event);
});
});
if (promises.length == events.length){
console.log("last run through");
q.all(promises).then(function(results){
console.log("all promises completed?");
console.log(results[0]); //OUTPUT BELOW
//more code in here... but promises haven't resolved
//...
dfd.resolve(events);
});
}
}
}else{
console.log("Not authenticated. Redirecting to main page.");
dfd.resolve(events);
}
});
return dfd.promise;
}
当我尝试获取一个JSON对象时,控制台上会返回一个未解决的promise,如下所示console.log(results[0]):
{ promise: [object Object],
resolve: [Function],
fulfill: [Function],
reject: [Function],
notify: [Function] }
我查阅的代码参考资料如下:
- https://github.com/kriskowal/q
- https://github.com/kriskowal/q/wiki/API-Reference
- https://strongloop.com/strongblog/how-to-compose-node-js-promises-with-q/
- http://thejsguy.com/javascript/node.js/2014/06/27/JavaScript-Flow-Control.html
另外,这是我编写的用于单个事件 fb/db 合并的函数,您可以进行比较:
function mergeEvent(req, res, next, event){
console.log("Merge Event");
var dfd = q.defer();
ensureAuthenticated(req, res, next).then(function(auth){
if (auth){
console.log("authenticated!");
console.log("auth token: " + ACCESS_TOKEN);
https.get('https://graph.facebook.com/' + event.fb_id + '?access_token=' + ACCESS_TOKEN, function(response) {
var str = '';
response.on('data', function(chunk){
str += chunk;
});
response.on('end', function(){
var fb_event = JSON.parse(str);
event.dataValues.fb = fb_event;
dfd.resolve(event);
});
});
}else{
console.log("not authenticated. redirecting to main page");
dfd.resolve(event);
}
});
return dfd.promise;
}