Обработка асинхронных обратных вызовов - PullRequest
1 голос
/ 26 июля 2011

У меня есть следующая функция:

    function IsFacebookOpen() {
    var url;
    var facebookFound = false;
    chrome.windows.getAll({"populate":true}, function(getInfo) {
        for(var j = 0; typeof getInfo[j] != "undefined"; j++) {
            for(var i = 0; typeof getInfo[j].tabs[i] != "undefined"; i++) {
                url = getInfo[j].tabs[i].url;
                if(url.substr(url.indexOf("facebook", 0), url.indexOf(".com", 0)-url.indexOf("facebook", 0)) == "facebook") {
                    facebookFound = true;
                }
            }
        }
    });
    return facebookFound;
}

Это проверяет, является ли одна из вкладок в Google Chrome Facebook.Проблема в том, что chromewindows.getAll является асинхронным, поэтому функции возвращаются до того, как все вкладки могут быть проверены.Это означает, что возвращаемое значение всегда ЛОЖНО, так как ни одна вкладка не проверяется перед возвратом.Если я заставлю функцию ждать, выполнив следующее:

function IsFacebookOpen() {
    var url;
    var facebookFound = false;
    var done = false;
    chrome.windows.getAll({"populate":true}, function(getInfo) {
        for(var j = 0; typeof getInfo[j] != "undefined"; j++) {
            for(var i = 0; typeof getInfo[j].tabs[i] != "undefined"; i++) {
                url = getInfo[j].tabs[i].url;
                if(url.substr(url.indexOf("facebook", 0), url.indexOf(".com", 0)-url.indexOf("facebook", 0)) == "facebook") {
                    facebookFound = true;
                    done = true;
                }
            }
        }
        done = true;
    });
    while(!done) { };
    return facebookFound;
}

функция никогда не вернется, но если я использую alert () и остановлю функцию на доли секунды, я получу правильное возвращаемое значение.Как я могу вернуть правильное значение без использования этого оповещения ()?

Ответы [ 3 ]

1 голос
/ 26 июля 2011

Вы делаете это неправильно.

function IsFacebookOpen(callback) {
    var url;
    chrome.windows.getAll({"populate":true}, function(getInfo) {
            for(var j = 0; typeof getInfo[j] != "undefined"; j++) {
            for(var i = 0; typeof getInfo[j].tabs[i] != "undefined"; i++) {
                url = getInfo[j].tabs[i].url;
                if(url.substr(url.indexOf("facebook", 0), url.indexOf(".com", 0)-url.indexOf("facebook", 0)) == "facebook") {
                    callback(true);
                }
            }
        }
        callback(false);
    });
}

// calling:
IsFacebookOpen(function (facebookOpen) {
    // insert code here
});

По аналогии с:

window.setTimeout(function () {
    // You put the code in here...
}, timeout);
// ... not in here.
1 голос
/ 26 июля 2011

Задумывались ли вы об использовании функции обратного вызова, как

fbOpenResponse(isOpened){
    // do stuff
}

что вы звоните, когда нашли (или нет) окно fb ...

Это может быть полезно.

0 голосов
/ 26 июля 2011

Ваша проблема в том, что Javascript может быть асинхронным, но он не является пареллом . Цикл занятости будет работать вечно и никогда не остановится, чтобы дать возможность запустить getAll после того, как все будет сделано.

Что вам нужно сделать, так это смириться с тем фактом, что ассинхронность "заразна", и превратить IsFacebookOpen в асинхронную функцию, как и в ответе Hello71.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...