我如何在Javascript中等待异步事件

How can I wait for asynchronous events in Javascript?

本文关键字:等待 异步 事件 Javascript      更新时间:2023-09-26

我是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()方法是异步的,这意味着用户名是空的。

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

您可以使用中间件来实现承诺,例如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));
            }
        });
    }
});

这是一个蓝鸟的例子,根据你的情况定制的:[它大量借用了Victor Quinn的例子]

使用与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);
});