Wie kann ich in Javascript auf asynchrone Ereignisse warten?
-
20-12-2019 - |
Frage
Ich bin neu in JavaScript und mit asynchronen Funktionen noch nicht vertraut ...
Ich arbeite mit node.js, um einen Chat-Server zu erstellen. Dies ist ein Teil meines Codes, der abgehört wird getListConnected
Ereignis und wenn es ausgelöst wurde, suchen Sie nach allen verbundenen clients
in einem bestimmten Namespace, und dann speichere ich für jeden Client seinen „Benutzernamen“ in einem anderen Array, konvertiere ihn in eine JSON-Antwort und sende dann:
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
});
Das Problem mit diesem Code besteht darin, dass die Methode client.get() asynchron ist, was bedeutet, dass Benutzernamen leer gesendet werden.
Wie kann ich auf Benutzernamen warten, bis sie gefüllt ist, oder wie kann ich auf die Schleife warten, bis sie fertig ist?
Lösung
Sie könnten Middleware für Versprechen verwenden, so etwas wie Bluebird, oder Sie könnten einen Zähler führen, um zu überprüfen, ob alle Benutzernamen abgerufen wurden, so etwas wie
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));
}
});
}
});
Andere Tipps
Hier ist ein Bluebird-Beispiel, angepasst an Ihre Situation:[es lehnt sich stark an Victor Quinns Beispiel]
Unter Verwendung derselben Promise-Definition, die Victor verwendet hat:
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;
};
Mit Ihrem benutzerdefinierten Aufruf instanziiert:
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);
});