【问题标题】:How can I wait for asynchronous events in Javascript?如何在 Javascript 中等待异步事件?
【发布时间】:2014-07-29 01:06:33
【问题描述】:

我是 JavaScript 新手,还不熟悉异步函数...

我正在使用 node.js 创建一个聊天服务器,这是我的代码的一部分,它监听 getListConnected 事件,当它触发它时,它会在给定的命名空间中查找所有连接的 clients,然后对于每个客户,我将他们的“用户名”存储到另一个数组中,将其转换为 JSON 响应,然后发送:

socket.on('getListConnected', function(msg){
                        var clients = namespace.clients();//get all client in that nsp
                        var usernames = Array() ;//init array
                        
                        for(i in clients)//for each clients
                        {
                           clients[i].get("username", function(value){
                               usernames.push(value);
                            });
                        }
                       socket.emit('getListConnected',JSON.stringify(usernames));//send
                    });

这段代码的问题是client.get() 方法是异步的,这意味着用户名是空的。

我如何等待用户名直到它被填满,或者我如何等​​待循环直到它完成?

【问题讨论】:

    标签: javascript node.js socket.io dom-events event-driven


    【解决方案1】:

    您可以将中间件用于承诺,例如Bluebird,或者您可以保留一个计数器来检查是否已获取所有用户名,例如

    socket.on('getListConnected', function (msg) {
        var clients   = namespace.clients();
        var usernames =  [];
        var counter1  =  0;
        var counter2  =  0;
    
        for (i in clients) {
    
            counter1++; // number of clients
    
            clients[i].get("username", function (value) {
                usernames.push(value);
                counter2++; // number of clients added to array
    
                if (counter1 === counter2) {
                    socket.emit('getListConnected', JSON.stringify(usernames));
                }
    
            });
        }
    
    });
    

    【讨论】:

    • thx,我会浏览 Bluebird,但在你的代码中是不行的,这可以在 c1=c2 时多次发送数组......但是有不同的想法是可以的!再次感谢!
    • 但是 c1 什么时候会和 c2 一样,除了每个用户名都被获取的时候。循环立即完成对第一个计数器的计数,异步函数在未来一段时间内完成第一个计数器的递增,然后递增第二个计数器。第一个计数器总是比异步计数器提前一步,所以它们唯一应该相同的时间是在末尾。
    • 不过我自己可能会选择 Bluebird、Q 或 async.js。
    【解决方案2】:

    这是一个针对您的情况定制的 Bluebird 示例: [它大量借用Victor Quinn's Example]

    使用与 Victor 相同的 Promise 定义:

    var Promise = require('bluebird');
    
    var promiseWhile = function(condition, action) {
        var resolver = Promise.defer();
    
        var loop = function() {
            if (!condition()) return resolver.resolve();
            return Promise.cast(action())
                .then(loop)
                .catch(resolver.reject);
        };
    
        process.nextTick(loop);
    
        return resolver.promise;
    };
    

    用您的自定义调用实例化:

    var i = 0;
    promiseWhile(function() {
        return i < clients.length;
    }, function(value) {
        return new Promise(function(resolve, reject) {
            clients[i].get("username", function(value){
                                           usernames.push(value);
                });
                i++;
                resolve();
        });
    }).then(function() {
        console.log("usernames are: " + usernames);
    });
    

    【讨论】:

      猜你喜欢
      • 2022-12-20
      • 1970-01-01
      • 1970-01-01
      • 2018-12-27
      • 1970-01-01
      • 1970-01-01
      • 2011-10-04
      • 1970-01-01
      • 2018-07-01
      相关资源
      最近更新 更多