Как я могу заставить XHR.onreadystatechange возвращать свой результат? - PullRequest
15 голосов
/ 19 марта 2011

Я новичок в программировании на JavaScript.Сейчас я работаю над расширением Google Chrome.Это код, который не работает ...: P

Я хочу, чтобы функция getURLInfo возвращала свой объект JSON, и хочу поместить его в resp.Может кто-нибудь исправить мой код, чтобы он заработал?

function getURLInfo(url)
{
    var xhr = new XMLHttpRequest();
    xhr.open
        (
            "GET",
            "http://RESTfulAPI/info.json?url="
                + escape(url),
            true
        );
    xhr.send();
    xhr.onreadystatechange = function()
    {
        if (xhr.readyState == 4)
        {
            return JSON.parse(xhr.responseText);
        }
    }
}
var resp = getURLInfo("http://example.com/") // resp always returns undefined...

Заранее спасибо.

Ответы [ 3 ]

24 голосов
/ 19 марта 2011

Здесь вы имеете дело с асинхронным вызовом функции.Результаты обрабатываются, когда они поступают, а не когда функция завершает работу.

Для этого предназначены функции обратного вызова.Они вызываются, когда результат доступен.

function get(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
            // defensive check
            if (typeof callback === "function") {
                // apply() sets the meaning of "this" in the callback
                callback.apply(xhr);
            }
        }
    };
    xhr.send();
}
// ----------------------------------------------------------------------------


var param = "http://example.com/";                  /* do NOT use escape() */
var finalUrl = "http://RESTfulAPI/info.json?url=" + encodeURIComponent(param);

// get() completes immediately...
get(finalUrl,
    // ...however, this callback is invoked AFTER the response arrives
    function () {
        // "this" is the XHR object here!
        var resp  = JSON.parse(this.responseText);

        // now do something with resp
        alert(resp);
    }
);

Примечания:

  • escape() устарела навсегда.Не используйте его, он не работает правильно.Используйте encodeURIComponent().
  • Вы могли бы сделать вызов send() синхронным, установив для параметра async для open() значение false.Это может привести к зависанию вашего пользовательского интерфейса во время выполнения запроса, а вы этого не хотите.
  • Существует множество библиотек, разработанных для обеспечения простоты и универсальности запросов Ajax.Я предлагаю использовать один из них.
3 голосов
/ 19 марта 2011

Вы не можете сделать это вообще для асинхронных вызовов XHR. Вы не можете заставить JavaScript «ждать» ответа HTTP от сервера; все, что вы можете сделать, это передать системе времени выполнения функцию для вызова (ваш обработчик), и она вызовет ее. Однако этот вызов будет долгое время после того, как код, который установил XHR, завершится.

Однако не все потеряно, так как эта функция-обработчик может сделать что угодно . Что бы вы ни хотели сделать с возвращаемым значением, вы можете сделать внутри обработчика (или из других функций, вызываемых из обработчика).

Таким образом, в вашем примере вы бы изменили что-то вроде этого:

    xhr.onreadystatechange = function()
    {
        if (xhr.readyState == 4)
        {
            var resp = JSON.parse(xhr.responseText);
            //
            // ... whatever you need to do with "resp" ...
            //
        }
    }
}
0 голосов
/ 17 апреля 2017

Для небольшого редактирования говорим о посте: https://stackoverflow.com/a/5362513/4766489

...
if (typeof callback == "function") {
     //var resp  = xhr.responseText;
     var resp  = JSON.parse(xhr.responseText);
     callback(resp);
}
...

А когда звонишь

...
function(data) {
    alert(data);
    /* now do something with resp */
}
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...