首先,原谅我,这对我来说是一个非常未知的领域......
得到以下信息:
app.get('/user/:user_id/followings', function(req, res) {
var response = {}
, userId = req.params.user_id
, ids = req.param('id').split(',')
, prefix = 'user'
, suffix = 'follower_ids';
for (var i=0; i<ids.length; i++) {
var id = ids[i]
, key = prefix+':'+ids[i];
console.log('1: ' + key);
checkMembership(userId, id, key, suffix, function(error, reply){
response[key] = reply;
console.log('2: ' + key + ': ' + reply);
});
}
res.json(response);
});
function checkMembership(userId, id, key, suffix, callback) {
var lookup = key+':'+suffix;
client.sismember(lookup, userId, callback);
}
对于以下路径:/ user / 1 / followings?id = 1,2,3,4,1000
我在控制台中得到了这个:
1: user:1
1: user:2
1: user:3
1: user:4
1: user:1000
2: user:1000: 0
2: user:1000: 1
2: user:1000: 1
2: user:1000: 1
2: user:1000: 0
这在浏览器中: {}
我发现它正在发生,因为东西是异步发生的......我只是不确定如何修复它。
checkMembership函数中记录的键错误。控制台应输出第二个回调,如下所示:
2: user:1: 0
2: user:2: 1
2: user:3: 1
2: user:4: 1
2: user:1000: 0
帮助!
答案 0 :(得分:4)
你是对的,因为checkMembership是异步的。因此,当checkMembership仍在等待答案时,你的for循环结束了。
让我们从简化您的示例开始:
for (i = 0; i < 3; i += 1) {
console.log('inside: ', i);
process.nextTick(function () {
console.log('outside: ', i);
});
};
console.log('end');
输出:
inside: 0
inside: 1
inside: 2
end
outside: 2
outside: 2
outside: 2
所以第一个问题是当计数器已经是2时执行回调。你可以通过创建一个闭包来解决这个问题。
for (i = 0; i < 3; i += 1) {
console.log('inside: ', i);
(function () {
var j = i;
process.nextTick(function () {
console.log('outside: ', j);
});
})();
};
console.log('end');
输出:
inside: 0
inside: 1
inside: 2
end
outside: 0
outside: 1
outside: 2
这将解决您response[key] = reply;
的问题。
此示例的第二个问题是在异步函数完成之前记录结束。在您的代码中,这意味着在res.json
完成设置键+回复之前将调用checkMembership
。
因此我们需要在记录结束之前找出所有回调的时间。既然你知道你的列表有多大,你也知道有多少回调。这意味着我们可以在每次回调完成时计算。如果计数相等,则知道所有回调都被调用。
在代码中它看起来像这样:
var size = 3;
var counter = 0;
var globalCallback = function () {
counter += 1;
if (counter === size) {
console.log('end');
}
}
for (i = 0; i < size; i += 1) {
console.log('inside: ', i);
(function () {
var j = i;
process.nextTick(function () {
console.log('outside: ', j);
globalCallback();
});
})();
};
我们的最终结果:
inside: 0
inside: 1
inside: 2
outside: 0
outside: 1
outside: 2
end
每次有一个异步函数列表时,我更喜欢使用控制流库,而不是像这样写一个计数器。像async.js这样的东西很受欢迎。
帮助我的是对我的代码有更实用的观点。您必须将其视为值列表以及要应用函数的每个值。这也是为什么async.js看起来有点像underscore.js。