Интуитивное сравнение
Согласно официальному определению из MDN Web Docs, Promise
- это объект, который представляет окончательное завершение или отказ асинхронного события. Это означает, что после создания Promise
он выполняется асинхронно и, когда он разрешается или отклоняется, результат передается в соответствующие функции-обработчики, и Promise
завершается. Так просто! Следующий пример демонстрирует эту простую функциональность:
Output: # After 5 seconds, both results are printed immediately Message: 1 2
Мы можем легко использовать Promise
s для выполнения HTTP-вызовов и для последовательного или параллельного выполнения нескольких вызовов, а также для простой обработки ошибок.
Но, глядя на этот код и вывод, мы видим, что Promise
s даже близко не подходят к идеальному подходу для взаимодействия с реактивными потоками данных.
Прежде всего, Promise
s выполняются в момент их объявления. В приведенном выше примере оба Promise
начали выполняться после того, как были объявлены. Вот почему результат второго Promise
распечатывается сразу после разрешения первого Promise
: первый Promise
разрешается через пять секунд, а второй разрешается через два, перед первым.
Во-вторых, нет механизма отмены Promise
- они неизменяемы. Это подразумевает серьезную проблему при работе с HTTP-вызовами, разрешение которых занимает много времени. В этом случае нам нужно будет полагаться на некоторые сторонние библиотеки для выполнения дополнительной логики.
И наконец, что наиболее важно, Promise
s обрабатывают источники данных, которые производят одно значение. При этом мы не можем использовать Promise
s для асинхронных последовательностей данных, таких как события мыши / клавиатуры.
Чтобы преодолеть эти недостатки, библиотека RxJS предоставляет средства для обработки всех асинхронных источников данных, будь то события мыши / клавиатуры или HTTP, одинаковым образом. В RxJS мы должны мыслить в терминах потоков, которые можно определить как последовательность событий, генерируемых во времени. Эти потоки состоят из нескольких компонентов (производителей, потребителей и конвейера данных). На данный момент нам нужно сосредоточиться только на производителе, который создается из чего-то, что асинхронно генерирует события во времени и отправляет их всем потребителям. В RxJS производители называются наблюдаемыми.
Следующий пример демонстрирует, как вышеупомянутые недостатки Promise
s могут быть преодолены с помощью наблюдаемых.
Я создаю наблюдаемые из событий мыши mousedown
, mouseup
и mousemove
. Я также связываю эти наблюдаемые и, наконец, подписываюсь на эту цепочку.
Перво-наперво - потоки асинхронных событий и связанный поток остаются бездействующими до тех пор, пока подписчик не начнет прослушивание. Таким образом, наблюдаемые объекты преодолевают один из основных недостатков Promise
s.
С другой стороны, если вы внимательно посмотрите на связанный наблюдаемый объект, я определяю условие для его отмены: когда генерируется событие mouseup
, отмените наблюдаемое и прекратите прослушивание. Мы также преодолеваем еще один серьезный недостаток Promise
s.
Наконец, мы можем сказать, что наблюдаемые могут работать с асинхронными значениями с течением времени, а не только с одним значением, как в случае Promise
s. В этом примере у меня есть три наблюдаемых объекта, созданных из событий мыши, и один связанный наблюдаемый объект, который начинает испускать значения при щелчке и перетаскивании мыши и останавливается при отпускании клавиши мыши.
Перед тем, как уйти, не забудьте проверить эту потрясающую анимацию о создании наблюдаемых из асинхронных событий.
Заботиться.