Как заставить наблюдаемые выполнить последовательность?

Я перехожу из мира обещаний в мир наблюдаемых. Одна вещь, которую я обычно делаю с Promise, - это связать ряд задач и заставить их работать последовательно. Например, у меня есть три задачи: printLog1() для печати 1 на консоли, printLog23() для печати 2 и 3 на консоли и printLog4() для печати 4.

Когда я хочу напечатать 1-2-3-4, я бы написал цепочку обещаний, как

printLog1()
  .then(() => {
    printLog23();
  })
  .then(() => {
    printLog4();
  });

Теперь я хочу иметь ту же функциональность с Observable, и я могу переписать printLog() в Observable, как

printLog1 = Rx.Observabale.of(1).map((i) => console.log(i));
printLog23 = Rx.Observabale.of(2, 3).map((i) => console.log(i));
printLog4 = Rx.Observabale.of(4).map((i) => console.log(i));

Тогда у меня есть три наблюдаемых, которые излучают разные значения на консоль. Как связать их так, чтобы эти три наблюдаемых выполнялись в порядке и печатали 1-2-3-4?

Ответ 1

Если вы хотите быть уверены, что порядок эмиссии такой же, как и порядок, в котором вы указали Наблюдаемые источника вы можете использовать concat или concatMap операторов.

Операторы concat* подписываются на Observable только после завершения предыдущего Observable (он также работает с Promises, см. Http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObservableInputDoc.html).

В вашем случае это будет выглядеть следующим образом:

import { concat } from 'rxjs'; // Note, concat from 'rxjs', is not the same as concat from 'rxjs/operators'

concat(printLog1, printLog23, printLog4);

... или с concatMap если запрос на одно Обещание зависит от ответа от предыдущего Обещания:

printLog1.pipe(
  concatMap(response => ...),
  concatMap(response => ...),
);

... или когда порядок не имеет значения, вы можете использовать функцию merge которая немедленно подписывается на все наблюдаемые/обещания и пересылает их результаты по мере их поступления:

merge(printLog1, printLog23, printLog4);

Январь 2019: обновлено для RxJS 6