Recently I’ve been studying RxJS, a library for responsive programming using Observables, which makes it easier to write asynchronous or callback-based code.

The following focuses on the differences between Observables and Promises.

Single-value versus multi-value

const numberPromise = new Promise((resolve) => { resolve(5); resolve(10) }); numberPromise.then(value => console.log(value)); // The output will only have 5Copy the code

Observables: Use next instead of resolve and subscribe instead of then.

const Observable = require('rxjs/Observable').Observable; const numberObservable = new Observable((observer) => { observer.next(5); observer.next(10); }); numberObservable.subscribe(value => console.log(value)); // Output 5, 10Copy the code

Observables subscribe continuously, which is a big difference from Promises. At ordinary times, we may encounter most of this situation is a request a response, but we will also have some situations:

  • SetInterval, resolve requires multiple values
  • webSockets
  • DOM events
const numberObservable = new Observable((observer) => {
      let i = 0;
      setInterval(() => { observer.next(i++); }, 1000); }); numberObservable.subscribe(value => console.log(value)); // Output 0, 1, 2, 3, 4, 5Copy the code

Code execution order

const promise = new Promise((resolve) => { console.log('promise call') resolve(1); Console. log(' Promise end')}) const Observable = new Observable(() => { console.log('I was called! '); }); // There is no console // just observable.subscribe(); This time I was called! Before it gets printed.Copy the code

Observables are lazy. They are executed only when someone subscribes.

If the top setInterval function is written in promises, but there is no promise. Then function, it wastes resources, and in Observables, memory is not allocated without subscribes.

Can’t cancel & can cancel

Promises cannot be cancelled by default and can be implemented using Bluebird, the promise implementation library. Bluebird is fully compatible with Promise and adds some useful methods.

const Observable = require('rxjs/Observable').Observable; const observable = new Observable((observer) => { let i = 0; const token = setInterval(() => { observer.next(i++); }, 1000); return () => clearInterval(token); }); const subscription = observable.subscribe(value => console.log(value + '! ')); setTimeout(() => { subscription.unsubscribe(); }, 5000) // Result 0! 1! 2! 3!Copy the code

The important thing to note here is that subscribe is not an Observable! That means you can’t subscribe as a chain as promise. Subscribe returns a Subscription to the specified Observable. He only has one method to call, unsubscribe.

Single subscription & Multiple subscriptions

Promises are radical. When a promise is created, it is already implemented and cannot be repeated.

let time; const waitOneSecondPromise = new Promise((resolve) => { console.log('promise call') time = new Date().getTime(); setTimeout(() => resolve('hello world'), 1000); }); WaitOneSecondPromise. Then ((value) = > {the console. The log (' for the first time, the value, new Date (). The getTime () - time)}); SetTimeout () = > {waitOneSecondPromise. Then ((value) = > {the console. The log (' second 'value, new Date (). The getTime () - time)}); }, 5000) // The output result is the first Hello World 1007 and the second Hello World 5006Copy the code

In the example above, I created a Promise, which is an immediate setTimeout, so the print interval in the first then function is approximately equal to 1s, which is what we expect, and we expect the promise to return after 1s. The second then function is executed after 5s, and the time difference between the start of the second Hello Word and promise is about 5s. Because resolve has been resolved after the 1s created by this promise, then is called without a 1s delay. Because promises are only executed once.

So obSRvables

const Observable = require('rxjs/Observable').Observable; let time; const waitOneSecondObservable = new Observable((observer) => { console.log('I was called'); time = new Date().getTime(); setTimeout(() => observer.next('hey girl'), 1000); }); WaitOneSecondObservable. Subscribe ((value) = > {the console. The log (' for the first time, the value, new Date (). The getTime () - time)}); SetTimeout () = > {waitOneSecondObservable. Subscribe ((value) = > {the console. The log (' second 'value, new Date().getTime() - time)}); }, 5000) // Output I was called first time hey girl 1003 I was called second time hey girl 1003Copy the code

This is the desired result, it will execute the monitored function again every time it subscribes, and whenever it wants to use the function, it just needs to subscribe again.

Multiple subscriptions are already possible with Observables, but this sometimes doesn’t fit our business scenario, where we might want to send a single request in an HTTP request, but the result is shared by multiple subscribers. Observables itself does not provide this functionality, but we can implement it using the RxJS library, which has a share operator.

Const waitOneSecondObservable = new Observable((observer) => {// send HTTP request}); const sharedWaitOneSecondObservable = waitOneSecondObservable.share(); sharedWaitOneSecondObservable.subscribe(doSomething); sharedWaitOneSecondObservable.subscribe(doSomethingElse); // Subscribe (); subscribe (); subscribe ();Copy the code

Always asynchronous & maybe asynchronous

const promise = new Promise((resolve) => { resolve(5); }); promise.then(value => console.log(value + '! ')); console.log('And now we are here.'); // And now we are here. 5!Copy the code

Although resolve is a synchronization thing in the Promise, it will execute the code first.

const Observable = require('rxjs/Observable').Observable; const observable = new Observable((observer) => { // observer.next(5); setTimeout(() => { observer.next(5); })}); observable.subscribe(value => console.log(value + '! ')); console.log('And now we are here.'); // If this is directly next 5, output is 5! SetTimeout next 5, And now we are here.-> 5!Copy the code

While promises are always asynchronous, Observables are more flexible and depend on their own functions, which is also dangerous. There are operators in RXJS that allow listening to be enforced asynchronously, such as observeOn.