Promise vs Observable

有人能解释一下Angular的PromiseObservable之间的区别吗?

每个例子都有助于理解这两种情况。 我们可以在哪种情况下使用每种情况?


诺言

Promise在异步操作完成或失败时处理单个事件

注意:有Promise库支持取消,但ES6 Promise目前还没有。

可观察

Observable就像一个Stream (在很多语言中),并允许传递零个或多个事件,其中为每个事件调用回调。

通常ObservablePromisePromise因为它提供了Promise等功能。 使用Observable ,如果要处理0,1个或多个事件,则无关紧要。 您可以在每种情况下使用相同的API。

Observable也有优于Promise的优势可取消 。 如果不再需要向服务器发送HTTP请求或其他昂贵的异步操作的结果,则ObservableSubscription允许取消订阅,而Promise最终将调用成功或失败的回调,即使您没有需要通知或其提供的结果。

Observable提供像mapforEachreduce操作符 ,类似于数组

还有像retry()replay()等强大的操作符,这些操作符通常非常方便。


公司承诺:

  • 返回单个值
  • 不可取消
  • try / catch和async / await更具可读性
  • 观测:

  • 随着时间的推移使用多个值
  • 撤销
  • 支持地图,过滤,减少和类似的操作
  • 使用Reactive Extensions(RxJS)
  • 其项目随时间异步到达的数组

  • PromisesObservables为我们提供了抽象,帮助我们处理应用程序的异步性。 @Günter和@Relu明确指出了它们之间的区别。

    由于代码片段胜过千言万语,请仔细阅读下面的示例,以更轻松地理解它们。

    感谢@Christoph Burgdorf提供的精彩文章


    Angular使用Rx.js Observable而不是承诺处理HTTP。

    假设你正在建立一个搜索功能 ,当你输入时应该立即显示你的结果。 听起来很熟悉,但这项任务有很多挑战。

  • 我们不希望每次用户按下某个按键时都会触发服务器端点,它应该以HTTP请求的风暴来填充它们。 基本上,我们只想在用户停止输入而不是每次按键时击中它。
  • 不要使用相同的查询参数为后续请求命中搜索端点。
  • 处理无序的响应。 当我们同时有多个请求在飞行中时,我们必须说明他们以意外的顺序返回的情况。 想象一下,我们首先键入电脑 ,停止,请求熄灭,我们键入 ,停止,请求熄灭。 现在我们有两个要求在飞行中。 不幸的是,携带计算机结果的请求在请求携带汽车结果后返回。
  • 该演示将包含两个文件: app.tswikipedia-service.ts 。 但是,在现实世界中,我们很可能会进一步分裂。


    下面是基于Promise的实现,它不处理任何描述的边缘情况。

    wikipedia-service.ts

    import { Injectable } from '@angular/core';
    import { URLSearchParams, Jsonp } from '@angular/http';
    
    @Injectable()
    export class WikipediaService {
      constructor(private jsonp: Jsonp) {}
    
      search (term: string) {
        var search = new URLSearchParams()
        search.set('action', 'opensearch');
        search.set('search', term);
        search.set('format', 'json');
        return this.jsonp
                    .get('http://en.wikipedia.org/w/api.php?callback=JSONP_CALLBACK', { search })
                    .toPromise()
                    .then((response) => response.json()[1]);
      }
    }
    

    我们正在注入Jsonp服务,以使用给定的搜索词对维基百科API进行GET请求。 请注意,我们调用toPromise以便从Observable<Response>Promise<Response> 。 最终以Promise<Array<string>>作为我们搜索方法的返回类型。

    app.ts

    // check the plnkr for the full list of imports
    import {...} from '...';
    
    @Component({
      selector: 'my-app',
      template: `
        <div>
          <h2>Wikipedia Search</h2>
          <input #term type="text" (keyup)="search(term.value)">
          <ul>
            <li *ngFor="let item of items">{{item}}</li>
          </ul>
        </div>
      `
    })
    export class AppComponent {
      items: Array<string>;
    
      constructor(private wikipediaService: WikipediaService) {}
    
      search(term) {
        this.wikipediaService.search(term)
                             .then(items => this.items = items);
      }
    }
    

    这里也没什么惊喜。 我们注入我们的WikipediaService并通过搜索方法向模板公开其功能。 模板只是结合KEYUP并调用search(term.value)

    我们解开了Promise的结果,即WikipediaService的搜索方法返回并将其作为简单的字符串数组展示给模板,以便我们可以通过*ngFor循环并为我们建立一个列表。

    请参阅Plunker上基于Promise的实现示例


    观察者真正发光的地方

    让我们更改我们的代码,使其不用每次击键都敲击端点,而是只在用户停止输入400毫秒时才发送请求

    为了揭示这样的超级权力,我们首先需要得到一个带有用户输入的搜索词的Observable<string> 。我们可以利用Angular的formControl指令,而不是手动绑定到keyup事件。 要使用此指令,我们首先需要将ReactiveFormsModule导入到我们的应用程序模块中。

    app.ts

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { JsonpModule } from '@angular/http';
    import { ReactiveFormsModule } from '@angular/forms';
    
    @NgModule({
      imports: [BrowserModule, JsonpModule, ReactiveFormsModule]
      declarations: [AppComponent],
      bootstrap: [AppComponent]
    })
    export class AppModule {}
    

    一旦导入,我们可以在我们的模板中使用formControl并将其设置为名称“term”。

    <input type="text" [formControl]="term"/>
    

    在我们的组件中,我们从@angular/form创建FormControl一个实例,并将其作为组件名称下的字段公开。

    在幕后, 术语会自动公开一个Observable<string>作为我们可以订阅的属性valueChanges 。 现在我们有一个Observable<string> ,克服用户输入就像在我们的Observable上调用debounceTime(400)一样简单。 这将返回一个新的Observable<string> ,它只会在400ms内没有传入新值时才会发出一个新值。

    export class App {
      items: Array<string>;
      term = new FormControl();
      constructor(private wikipediaService: WikipediaService) {
        this.term.valueChanges
                  .debounceTime(400)        // wait for 400ms pause in events
                  .distinctUntilChanged()   // ignore if next search term is same as previous
                  .subscribe(term => this.wikipediaService.search(term).then(items => this.items = items));
      }
    }
    

    如果我们的应用已经显示搜索结果,则发送另一个搜索字词的请求会浪费资源。 我们所要做的就是在我们调用debounceTime(400)后立即调用distinctUntilChanged操作符,

    请参阅Plunker上的Observable实现示例

    为了处理乱序的反应,请查看全文http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

    至于我在Angular中使用Http,我同意在正常使用情况下使用Observable over Promise没有太大的区别。 在实践中,这些优势都没有真正相关。 希望我可以在未来看到一些高级用例:)


    学到更多

  • https://angular-2-training-book.rangle.io/handout/observables/
  • https://angular.io/tutorial/toh-pt6#observables
  • 链接地址: http://www.djcxy.com/p/9447.html

    上一篇: Promise vs Observable

    下一篇: How do I access previous promise results in a .then() chain?