Как заставить Javascript выполнять последовательно

У меня есть страница, где пользователь может нажать кнопку, чтобы получить данные с помощью запроса xhr get. Пока данные загружаются и анализируются, я хочу, чтобы отображалось загрузочное сообщение, которое будет заменено данными, как только они будут готовы. Я использую библиотеки dojo, поэтому предпочел бы не включать jQuery или другие библиотеки.

Это упрощенная версия установки, которую я использую:

HTML

<div id = "clickMe"> Click Me! </div>
<div id = "results" class = "hidden">
    Please wait while we retrieve the results
</div>

CSS

.hidden {display: none;}

Javascript

// Bind function to click me div
var clickMe = document.getElementById('clickMe');
clickMe.addEventListener('click', getResults, false);

function getResults () {
    // Display the loading message while results are retrieved
    var resultsDiv = document.getElementById('results');
    resultsDiv.classList.remove('hidden');

    // Get the data and parse it here using a standard dojo.xhrGet method
    var displayResults = getData();

    // Output data to resultsDiv, overwriting loading message
    resultsDiv.innerHTML = displayResults;
}

У меня проблема в том, что функция getResults всегда ждет завершения функции getData, прежде чем удалить "скрытый" класс и показать результат div. Это означает, что пользователь никогда не видит сообщение о загрузке, только полученные данные, даже если есть задержка во время обработки данных. Однако, если я поставлю предупреждение посередине, функция будет вынуждена приостановиться, появится сообщение о загрузке:

function getResults () {
    // Display the loading message while results are retrieved
    var resultsDiv = document.getElementById('results');
    resultsDiv.classList.remove('hidden');

    // The loading message will be displayed if this alert is included
    alert ("Hello world!");

    // Get the data and parse it here using a standard dojo.xhrGet method
    var displayResults = getData();

    // Output data to resultsDiv, overwriting loading message
    resultsDiv.innerHTML = displayResults;
}

Я попытался заменить предупреждение на console.log, но оно перестает отображать сообщение о загрузке. Я также попытался настроить получение данных в качестве функции обратного вызова при отображении сообщения о загрузке, но опять-таки ничего не отображается. Я также попытался с запросом get, установленным для sync: true и sync: false, но опять же не повезло.

Как я могу убедиться, что сообщение о загрузке отображается во время ожидания getData?

Редактировать:

Это функция getData. Я пробовал как с синхронизацией, так и без нее.

function getData() {
    var targetUrl = //some url;
    var restResponse;

    dojo.xhrGet({

        url: targetUrl,
        sync: true; // no difference when this is omitted

        load: function(result) {
            restResponse = result;
        }

    });

    // Parse the rest response - fairly long function so I won't paste it here
    var parsedResponse = parseResult(restResponse);

    return parsedResponse;
}

2 ответа

Решение

Моя рекомендация состоит в том, чтобы научиться писать асинхронный код и dojo/Deferred.

Вместо getData, переименуйте метод в loadData а также

loadData: function() {
    return xhr('', {...}); // this returns a deferred
}

function getResults () {
    var resultsDiv = dom.byId('results');
    domClass.remove(resultsDiv, 'hidden');

    loadData().then(function(displayResults) {
        resultsDiv.innerHTML = displayResults;
    });        
}

http://dojotoolkit.org/reference-guide/1.9/dojo/Deferred.html

Вы можете использовать deffereds и обещания в JQuery

http://www.bitstorm.org/weblog/2012-1/Deferred_and_promise_in_jQuery.html. Если вы работаете с ajax-запросом, вы можете создать цепочку следующим образом (начиная с jQuery 1.8).

var promise1 = $.ajax("/myServerScript1");

function getStuff() {
    return $.ajax("/myServerScript2");
}

promise1.then(getStuff).then(function(myServerScript2Data){
  // Both promises are resolved
});
Другие вопросы по тегам