Подтвердить что ты не робот

Как я могу заставить XHR.onreadystatechange вернуть результат?

Я новичок в программировании 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...

Спасибо заранее.

4b9b3361

Ответ 1

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

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

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. Я предлагаю использовать один из них.

Ответ 2

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

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

Таким образом, в вашем примере вы бы изменили такие вещи:

    xhr.onreadystatechange = function()
    {
        if (xhr.readyState == 4)
        {
            var resp = JSON.parse(xhr.responseText);
            //
            // ... whatever you need to do with "resp" ...
            //
        }
    }
}

Ответ 3

Для небольшого редактирования, говорящего о сообщении: fooobar.com/info/430119/...

...
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 */
}
...