سؤال

أنا جديد على 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() غير متزامنة وتعني أنه يتم إرسال أسماء المستخدمين فارغة.

كيف يمكنني انتظار أسماء المستخدمين حتى يتم ملؤها، أو كيف يمكنني انتظار الحلقة حتى تنتهي؟

هل كانت مفيدة؟

المحلول

يمكنك استخدام البرامج الوسيطة للوعود، شيء من هذا القبيل طائر أزرق, ، أو يمكنك الاحتفاظ بعداد للتحقق مما إذا تم الحصول على جميع أسماء المستخدمين، مثل

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));
            }

        });
    }

});

نصائح أخرى

إليك مثال بلوبيرد، المخصص لموقفك:[يقترض بشدة من مثال فيكتور كوين]

باستخدام نفس تعريف الوعد الذي استخدمه فيكتور:

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);
});
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top