Как реализовать функцию-получатель (используя обратные вызовы) - PullRequest
2 голосов
/ 09 сентября 2010

Мне нужно запросить данные для JS-скрипта из базы данных MySQL (на основе идентификатора пользователя).

Я не нашел простого решения для JavaScript, и было невозможно загрузить данные с помощью ajax, поскольку база данных доступна в другом домене.

Я реализовал обходной путь, используя PHP и curl.
Теперь JS должен «дождаться» завершения запроса, но, конечно, скрипт работает асинхронно и не ждет ответа.
Я знаю, что на самом деле нельзя ждать в JS, но должно быть возможно возвращать значение, подобное этому.

Я также пытался использовать return в качестве другого обратного вызова, но это, конечно, не сработало, потому что функция getter будет работать дальше.

Как я могу реализоватьпростой геттер, который «ждет» и возвращает ответ от HTTP-запроса?

Спасибо за любые другие подсказки.Я действительно потерян в данный момент.
Это выдержка из исходного кода:

/**
 * Simple getter which requests external data
 */
function simple_getter() {

    // http request using a php script, because ajax won't work crossdomain
    // this request takes some time. function finished before request is done.

    /* Example */
    var url = "http://example-url.com/get_data.php?uid=1234";
    var response_callback = handle_result_response;

    var value = send_request( url, response_callback );

    value = value.split('*')[0];

    if (value === '' || value == const_pref_none) {
        return false;
    }

    /* 1. returns undefinied, because value is not yet set.
       2. this as a callback makes no sense, because this function
          will run asynchronous anyway. */
    return value;
}

Дополнительная информация об используемых функциях:

/**
 * Callback for the send_request function.
 * basically returns only the responseText (string)
 */
function handle_result_response(req) {
    // do something more, but basically:
    return req.responseText;
}

/**
 * Requests data from a database (different domain) via a PHP script
 */
function send_request( url, response_callback ) {
    var req = createXMLHTTPObject();

    if (!req)
        return;

    var method = (postData) ? "POST" : "GET";

    req.open(method, url, true);
    req.setRequestHeader('User-Agent','XMLHTTP/1.0');

    // More not relevant source code
    // ...

    req.onreadystatechange = function () {
        // More not relevant source code
        // ...

        response_callback(req);
    }

    if (req.readyState == 4)
        return;

    req.send(postData);

}

Не совсем соответствующий код, но требуется для HTTP-запроса:

var XMLHttpFactories = [
    function () {return new XMLHttpRequest()},
    function () {return new ActiveXObject("Msxml2.XMLHTTP")},
    function () {return new ActiveXObject("Msxml3.XMLHTTP")},
    function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];


function createXMLHTTPObject() {
    var xmlhttp = false;

    for (var i=0; i<XMLHttpFactories.length; i++) {

        try {
            xmlhttp = XMLHttpFactories[i]();
        } catch (e) {
            continue;
        }

        break;
    }

    return xmlhttp;
}

Ответы [ 3 ]

3 голосов
/ 09 сентября 2010

Вы действительно не должны пытаться синхронно ждать завершения сетевого запроса.Запрос может никогда не исполниться, может зависнуть и занять много времени, и так далее.Поскольку JavaScript является однопоточным, и на самом деле все основные механизмы браузера являются однопоточными, это приведет к зависанию всей страницы при ожидании запроса, а в некоторых браузерах может вызвать зависание всего браузера.

Вам следует заменить код, подобный следующему:

var returned = some_request('http://example.com/query');
do_something_with(returned);

, на код, подобный следующему:

some_request('http://example.com/query', function (returned) {
  do_something_with(returned);
});

Таким образом, вы никогда не заставите свою страницу или браузер зависать в ожиданиизапрос, и может просто сделать работу, как только ответ приходит.

0 голосов
/ 09 сентября 2010

Так работают клиентские приложения.Это не процедурно, а работает по событиям.

  1. Вы представляете экран пользователю и ждете
  2. Пользователь совершает действие
  3. Вы звоните на сервер, устанавливаете обратный вызов и ждете
  4. Ответ приходит, и вы выполняете обратный вызов и ждете другого шага. 2

Вместо того, чтобы пытаться изменить это, вам нужно соответствовать этому, или это будет болезненный опыт.

Javascript не является многопоточным.Это означает, что один оператор выполняется одновременно.Настоящий асинхронизм возникает из-за времени, которое требуется серверу, чтобы ответить и вызвать обратный вызов.Вы никогда не знаете, какой вызов придет первым, и вам нужно создать свою программу с учетом этого.

0 голосов
/ 09 сентября 2010

Я не вижу, что не так с вашим кодом в целом.

Когда вы делаете запрос, предоставьте обратный звонок.Когда возвращается ответ, который вы можете легко обнаружить, выполните Callback и передайте ему результат.

...