oma*_*ous 0 javascript asynchronous redis node.js express
首先,请原谅我,因为这对我来说是一个未知的领域。
得到以下内容:
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
救命!
您说对了,因为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的原因。