2011-11-01 49 views
3

请问我可以就节点和redis的控制流问题提出一些建议吗? (又名Python编码器试图适应JavaScript)节点/ redis和回调控制流问题?

我不明白为什么client.smembersclient.get(Redis查找)需要回调而不是简单地作为语句 - 它使生活变得非常复杂。

基本上我想查询一个集合,然后当我得到集合的结果时,我需要对每个结果执行get操作。 当我得到所有数据时,我需要将其广播回客户端。

目前我在两个回调中使用一个全局对象,这似乎凌乱。我甚至不确定它是否安全(在启动另一个代码之前代码是否会等待一个client.get完成)?

当前的代码看起来是这样的:

var all_users = []; 
// Get all the users for this page. 
client.smembers("page:" + current_page_id, function (err, user_ids) { 
    // Now get the name of each of those users. 
    for (var i = 0; i < user_ids.length; i++) { 
    client.get('user:' + user_ids[i] + ':name', function(err, name) { 
     var myobj = {}; 
     myobj[user_ids[i]] = name; 
     all_users.push(myobj); 
     // Broadcast when we have got to the end of the loop, 
     // so all users have been added to the list - 
     // is this the best way? It seems messy. 
     if (i === (user_ids.length - 1)) { 
      socket.broadcast('all_users', all_users); 
     } 
    });  
    } 
}); 

但这似乎很凌乱。这是否真的是最好的方法?在致电socket.broadcast之前,我如何确定所有查询都已执行?

划痕头在此先感谢您的任何建议。

回答

1

我不明白为什么client.smembersclient.get(Redis的查找)必须回调,而不是简单地陈述 - 它使生活很复杂。

这就是Node。 (我敢肯定,这个主题是超过这里足够的时间讨论,期待通过其他疑问,这绝对是有)

我如何能够确保所有查询都调用socket.broadcast之前执行?

这就是回调函数中的err。这是有点节点的标准 - 回调中的第一个参数是错误对象(如果一切正常,则为null)。因此,只要使用这样的事情,以确保没有发生任何错误:

if (err) { 
    ... // handle errors. 
    return // or not, it depends. 
} 

... // process results 

但这似乎很凌乱。

你会习惯它的。我实际上发现它很好,当代码格式良好并且项目结构巧妙时。

其他方式是:

  • 使用库控制异步代码流(Async.jsStep.js等)
  • 如果意大利面条式的代码是什么你认为是乱七八糟的,定义一些函数来处理结果并将它们作为参数而不是匿名参数传递。这个变型的缺点是,只有一个用户名会在同一时间内获取

    var all_users = []; 
    // Get all the users for this page. 
    var user_ids = client.smembers("page:" + current_page_id, _); 
    // Now get the name of each of those users. 
    for (var i = 0; i < user_ids.length; i++) { 
        var name = client.get('user:' + user_ids[i] + ':name', _); 
        var myobj = {}; 
        myobj[user_ids[i]] = name; 
        all_users.push(myobj); 
    } 
    socket.broadcast('all_users', all_users); 
    

    注:

+1

1人[流程](https://github.com/willconant/flow-js) –

+0

共与提问观测同意,我也在为这些概念而苦苦挣扎。 “这就是节点”,似乎有点嚣张,对不起。 –

+0

@SSHTh在Node的网站的[main page](http://nodejs.org/)上正确表示异步I/O。我只能推测出一些原因,这些原因使你选择依赖于你不知道(也不愿意)理解的概念的技术。尝试获得它,如果不是,你会爱上它 - 选择不同的东西。 – elmigranto

0

如果你不喜欢完全写东西回调风格,你可能会想尝试streamlinejs。另外,你还应该知道这个代码的真正用处。

+0

很好的答案,谢谢。不过,我想知道:写回调式的正确方法是什么?就这样,我知道正确的方式之前,以简单的方式:) – Richard

0

Async是一个伟大的图书馆,你应该看看。为什么?清洁代码/过程/易于追踪..等

另外,请记住,所有的异步函数将在for循环后处理。以您为例,可能会导致错误的“我”值。使用封闭:

for (var i = 0; i < user_ids.length; i++) { (function(i) { 
client.get('user:' + user_ids[i] + ':name', function(err, name) { 
    var myobj = {}; 
    myobj[user_ids[i]] = name; 
    all_users.push(myobj); 
    // Broadcast when we have got to the end of the loop, 
    // so all users have been added to the list - 
    // is this the best way? It seems messy. 
    if (i === (user_ids.length - 1)) { 
     socket.broadcast('all_users', all_users); 
    } 
});  
})(i)} 

你应该做的知道什么时候完成什么是使用像异步递归模式(我认为)做的。你自己做这件事很简单。

async.series({ 
    getMembers: function(callback) { 
    client.smembers("page:" + current_page_id, callback); 
    } 
}, function(err, results) { 
    var all_users = []; 
    async.forEachSeries(results.getMembers, function(item, cb) { 
    all_users.push(item); 
    cb(); 
    }, function(err) { 
     socket.broadcast('all_users', all_users); 
    }); 
}); 

此代码可能不是有效的,但你应该能够弄清楚如何去做。

步骤库也不错(并且只有30〜行的代码我觉得)

+0

对于循环,他也可以做​​.forEach – thejh