Как заставить 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
});