XHR OnLoad Promise блокирует другие обратные вызовы OnLoad

Я пытаюсь загрузить файлы со своего сервера, а затем запустить Promises для загруженных данных. Моя проблема в том, что кажется, что мои обещания по какой-то причине блокируют все:

Он начинает загрузку ВСЕХ файлов, как только первый файл загружен, он блокирует загрузку других и запускает полную цепочку обещаний обратного вызова onLoad, а затем продолжает загрузку оставшихся файлов. После завершения создания нового файла он блокирует другие загрузки, запускает цепочку обещаний и так далее.

Мой обратный вызов onload содержит следующее:

function(response) {

  window.console.log('on load callback...');

      var sequence = Promise.resolve();
      sequence
      .then(function(){
        sleep(10000);
        window.console.log('sleep 1 is over...');
        return 'DONE!';
      })
      .then(function(){
        sleep(10000);
        window.console.log('sleep 2 is over...');
        return 'DONE!';
      })
      .then(function(){
        sleep(10000);
        window.console.log('sleep 3 is over...');
        return 'DONE!';
      });
}

И моя функция сна следующая:

 function sleep(milliseconds) {
   var start = new Date().getTime();
   for (var i = 0; i < 1e7; i++) {
     if ((new Date().getTime() - start) > milliseconds){
       break;
    }
  }
 }

В консоли возвращается:

on load callback...
sleep 1 is over...
sleep 2 is over...
sleep 3 is over...
on load callback...
sleep 1 is over...
sleep 2 is over...
sleep 3 is over...
on load callback...
sleep 1 is over...
sleep 2 is over...
sleep 3 is over...
on load callback...
sleep 1 is over...
sleep 2 is over...
sleep 3 is over...

Любая помощь будет оценена.

Я могу понять, что загрузка блокируется, когда выполняется «спящий режим», но я не понимаю, почему он запускает все «спящий режим 1», «спящий режим 2» и «спящий режим 3», прежде чем продолжить загрузку оставшихся файлов.

==== РЕДАКТИРОВАТЬ ====

Я загружаю файлы с помощью «обещанного» XMLHttpRequest и Promise.all (). (http://www.html5rocks.com/en/tutorials/es6/promises/ < / а>)

С уважением, Николас


person Nicolas    schedule 02.06.2015    source источник
comment
Где код, соответствующий загрузке?   -  person thefourtheye    schedule 02.06.2015
comment
Я добавил информацию в РЕДАКТИРОВАТЬ. Здесь нет никакой магии, я использовал обещанный XMLHttpRequest, построил свой массив последовательностей для каждого файла, а затем мог Promise.all ().   -  person Nicolas    schedule 02.06.2015


Ответы (2)


Я думаю, что вы спрашиваете здесь (с этой ужасной функцией ожидания-ожидания sleep (), которую никто никогда не должен использовать в реальном коде), почему все функции .then() имеют приоритет над событиями onload в цикле событий JS?

Они это делают, и это потому, что обещания выполняются в очереди микро-задач, которая отделена от основной очереди задач и истощается раньше последней.

См. Также этот ответ на другой вопрос.

person jib    schedule 02.06.2015
comment
ОК, это имеет смысл. Я предполагаю, что это также причина, по которой появился API-интерфейс fetch, поскольку он полностью обещан! Кажется, XHR не слишком хорошо справляется с обещаниями. - person Nicolas; 05.06.2015

но я не понимаю, почему он запускает все «сна 1», «сна 2» и «сна 3», прежде чем продолжить загрузку оставшихся файлов.

Обратные вызовы Promise в основном выполняются в произвольном порядке 1, когда есть несколько обещаний, ожидающих своего разрешения. В вашем случае он просто решил запустить этот sequence обратных вызовов (каждый из которых, к сожалению, занимает очень много времени), прежде чем вернуться к onload обратным вызовам ваших запросов ajax, которые разрешают другие обещания, и перед запуском их обратных вызовов, которые продолжают загрузку из оставшихся файлов.

Решение довольно простое: не используйте sleep и не используйте долго выполняющийся код (но сделайте его асинхронным).

1: Конечно, обратные вызовы в цепочке (.then(A).then(B)) должны выполняться в порядке обещаний.
И Promises / A + требует, чтобы несколько обратных вызовов для одного и того же обещания выполнялись в порядке регистрации (p.then(A); p.then(B);).
И ECMAScript6 требует, чтобы обратные вызовы для нескольких разрешенных обещаний выполнялись в порядке разрешения обещаний.

person Bergi    schedule 02.06.2015
comment
Спасибо, сон был всего лишь фиктивным примером, демонстрирующим проблему. Мне было интересно, почему он заканчивает последовательность перед запуском другой последовательности. Похоже, это связано с тем, что события promises и onLoad не выполняются в одной очереди задач, верно? - person Nicolas; 05.06.2015
comment
@Nicolas: Да, это возможное объяснение; хотя браузеры afaik не обязаны сначала обрабатывать очередь обещаний. Конечно, sleep был всего лишь пустышкой, но я имел в виду, что обычно вы не испытываете никаких проблем с параллелизмом, пока все ваши асинхронно выполняемые фрагменты будут быстрыми (а не длительными). - person Bergi; 05.06.2015