Если вам действительно нужны синхронные запросы, вы обычно можете направить соответствующий механизм AJAX для этого. Например, в jQuery вы устанавливаете для async
значение значение false. При использовании XMLHttpRequest вы передаете false в качестве третьего параметра open
(именно так Раман реализует sleep
в сообщении блога, на которое вы ссылаетесь). Тем не менее, SJAX, как правило, плохо, поскольку он блокирует выполнение JS в текущих браузерах. Лучше использовать стиль передачи продолжения , передав функцию для выполнения остальной части вычисления:
framework = {
require: function(urls, done)
{
function success(data, textStatus, jqXHR)
{
//...
}
function error(jqXHR, textStatus, errorThrown)
{
//...
}
urls.unshift('');
function load() {
urls.shift();
if (urls.length) {
$.ajax({
url: urls[0],
// here are some continuations
complete: load,
success: success,
error: error
});
} else {
// here's a continuation invocation
done();
}
}
}
};
Если вместо синхронности вам нужно выполнить какое-то действие, когда все данные ресурсы загружены, вы можете использовать продолжение для действия, но не для загрузки ресурсов. Вместо этого вы просто применили бы модель обработки событий, записывая завершение каждой загрузки и вызывая зависимое действие после завершения всех запросов ресурсов.
framework = {
require: function(urls, done)
{
var remaining = urls.length;
var failed=[];
// The following implementation is vulnerable to race conditions.
// Good thing JS isn't generally multithreaded. If (when) it is,
// and if the browser doesn't offer some form of synchronization,
// then Peterson's algorithm should work correctly if inefficiently.
function success(data, textStatus, jqXHR) {
if (!--remaining) { // critical section
done(failed);
}
}
function makeErrorHandler(url) {
return function (jqXHR, textStatus, errorThrown) {
failed.push(url);
if (!--remaining) { // critical section
done(failed);
}
}
}
for (var i=0; i < urls.length; ++i) {
$.ajax({
url: urls[i],
success: success,
error: makeErrorHandler(urls[i])
});
}
}
};