Цепочки обещаний не выполняются последовательно с использованием библиотеки обещаний Q

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

Вот jsfiddle, который я создал. Посмотрите на консоль, там весь вывод. А вот код для удобства:

asyncChain(10, 'FIRST CHAIN')
.then(function () {
  asyncChain(10, 'SECOND CHAIN');
})
.then(function(){
  asyncChain(10, 'THIRD CHAIN');
});

function asyncChain(n, msg) {
  var promiseChain = Q.fcall(function () {
    10;
  });
  console.log('starting:' + msg);
  for (var i = 0; i < n; i++) {
    promiseChain = promiseChain.then(asyncOperation(i, msg));
  }
  console.log('returning' + msg);
  return promiseChain;
}

function asyncOperation(i, msg) {
  var d = Q.defer();

  setTimeout(function () {
    console.log('resolving for #' + i + msg);
    d.resolve(i);
  }, 300 + Math.random()*1000);

  return d.promise;
}

По сути, это 3 пакетных операции обещания, которые, как я ожидаю, будут завершены одна за другой. Это означает, что вывод для этого примера будет примерно таким:

starting FIRST CHAIN
returning FIRST CHAIN
resolving 1..10 FIRST CHAIN

starting SECOND CHAIN
returning SECOND CHAIN
resolving 1..10 SECOND CHAIN
and so on

Я попытался использовать метод all() вместо then(), но он остановил выполнение после первой цепочки. Я упускаю что-то очевидное?

Спасибо за любой совет.

Ваше здоровье


person Naz    schedule 21.09.2013    source источник
comment
В пакетах под асинхронностью вы по-прежнему подразумеваете последовательно, а не параллельно?   -  person Bergi    schedule 23.09.2013
comment
Я имел ввиду последнее.   -  person Naz    schedule 23.09.2013


Ответы (1)


Я упускаю что-то очевидное?

Да. Чтобы then разрешил промис другим промисом, вы должны вернуть это другое промис. Ваша функция просто запускает еще один asyncChain, но возвращает undefined из обратного вызова, который немедленно разрешает обещание.

asyncChain(10, 'FIRST CHAIN').then(function () {
  return asyncChain(10, 'SECOND CHAIN');
}).then(function(){
  return asyncChain(10, 'THIRD CHAIN');
});
person Bergi    schedule 23.09.2013
comment
Спасибо, что указали на это, я думаю, что просто потратил слишком много времени на изучение одного и того же кода :) Я также обнаружил, что использование метода thenResolve делает синтаксис немного более читаемым, а анонимные функции не нужно определять. - person Naz; 23.09.2013
comment
Но thenResolve не ждет первого промиса, прежде чем он оценит asyncChain(…), снова делая его параллельным? - person Bergi; 23.09.2013
comment
thenResolve() — это просто сахар для функции(){}. Проверьте это на ‹a href='github.com/kriskowal/q/. blob/master/q.js'› источник -‹/a› строка 846. - person Naz; 24.09.2013
comment
Да, но есть огромная разница, когда вычисляется value… Когда asyncChain вызывается до того, как результат передается в thenResolve, все вызовы будут выполняться параллельно. Когда он вызывается в анонимной функции, которая передается then, они будут выполняться последовательно. - person Bergi; 24.09.2013