What are the differences between observables and promises in JavaScript?

后端 未结 7 761
隐瞒了意图╮
隐瞒了意图╮ 2020-12-23 12:48

So i\'ve read that observables are looking to overtake promises in terms of usage in some of upcoming JavaScript MVC\'s:

  • Angular 2.0
  • Falcor used by Ne
相关标签:
7条回答
  • 2020-12-23 13:51

    When you understand Observables correctly, the differences to Promises are pretty obvious.

    The best way to demystify a convoluted concept is to implement it from scratch. Here is an almost purely functional Observable implementation and an example, that wouldn't work with Promises:

    /*** Observable type ***/
    
    // type constructor (of a product type)
    
    const proType = name => cons => {
      const f = (k, ...args) =>
        Object.defineProperties({["run" + name]: k}, {
          [Symbol.toStringTag]: {value: name},
          [Symbol("args")]: {value: args}
        });
    
      return cons(f);
    };
    
    // value constructor
    
    const Observable = proType("Observable")
      (Observable => k => Observable(k));
    
    /*** Observer factory ***/
    
    const Observer = observer => {
      let isUnsubscribed = false;
    
      return {
        next: function(x) {
          if (isUnsubscribed)
            throw new Error("unsubscribed");
    
          else {
            try {
              return observer.next(x);
            }
    
            catch(e) {
              isUnsubscribed = true;
              this.cancel();
              throw e;
            }
          }
        },
    
        error: function(e) {
          if (isUnsubscribed)
            throw new Error("unsubscribed");
    
          else {
            try {
              return observer.error(e);
            }
    
            catch(e_) {
              isUnsubscribed = true;
              this.cancel();
              throw e_;
            }
          }
        },
    
        complete: function() {
          if (isUnsubscribed)
            throw new Error("unsubscribed");
    
          else {
            try {
              const r = observer.complete();
              this.cancel();
              return r;
            }
    
            catch(e) {
              isUnsubscribed = true;
              cancel();
              throw e;
            }
          }
        }
      };
    };
    
    /*** combinators + auxiliary functions ***/
    
    const subscribe = observable => handlers => {
      const observer = Observer(handlers),
        cancel = observable.runObservable(observer);
    
      observer.cancel = cancel;
      return cancel;
    };
    
    const obsMap = f => observable =>
      Observable(observer => {
        const mapObserver = {
          next: x => observer.next(f(x)),
          error: e => observer.error(e),
          complete: () => observer.complete()
        };
    
        return observable.runObservable(mapObserver);
      });
    
    /*** main ***/
    
    // create an Observable instance
    
    const numStream = Observable(observer => {
      let i = 0;
    
      const timer = setInterval(() => {
        observer.next(i++);
      }, 1000);
      
      return () => clearTimeout(timer);
    });
    
    // map a function over it
    
    const squaredNumStream =
      obsMap(x => x * x) (numStream);
    
    // run the observable
    
    const cancel = subscribe(squaredNumStream) ({
      next: x => console.log(x),
      error: e => console.error(e),
      complete: () => console.log("finished")
    });
    
    // cancel it
    
    setTimeout(cancel, 11000);

    In the example above the Observable squaredNumStream emits a stream of theoretically infinite values asynchronously. You cannot do this with Promises, because they represent a single future value.

    I could have easily subscribed to another squaredNumStream without both instances interfering with each other. This is because Observables are unicast, whereas Promises are multicast.

    squaredNumStream doesn't run at declaration time, but only after subscription, because Observables are lazily evaluated. Promises on the other hand are eagerly evaluated that is, they start running as soon as you create them.

    And finally, Observables are cancelable by design, whereas Promises are hard to cancel due to there unicast semantics.

    0 讨论(0)
提交回复
热议问题