【问题标题】:Reactive programming with Javascript使用 Javascript 进行反应式编程
【发布时间】:2016-06-29 03:51:47
【问题描述】:

我是响应式编程的新手,阅读所有这些我无法理解的文章我有点迷茫。

实际上,我是一名来自 Nodejs、Angularjs、Angular 2 和 React 的 javascript 开发人员。

我做什么

我一直使用 Promise,用于远程数据获取、本地异步解析等...比回调更好的可测试性并满足我的需求。

我对流的理解

我不知道流在哪里可以拯救我,除非在特殊情况下。

这种特殊情况是我不能在监听流时使用 Promise,因为 Promise 只会被解析一次。

SocketIo 示例:

io.on('connection',  (socket) => {
  // this works
});

io.on('connection').then((socket) => {
  // this can't work, promise would be resolved only once
});

如果我没记错的话,我可以通过简单地返回一个 observable 来使用响应式流来管理这种情况。对吧?

我不明白的地方

我正在研究 Angular 2 和周围的所有东西。实际上,在许多博客中,人们习惯于使用 observables 来获取远程数据,我无法理解使用它而不是 promises 有什么优势。

事实上,在这两种情况下我都需要制作一个遥控器,那么为什么一个比另一个多呢?这是性能问题吗?

我需要什么

如果您已经阅读了整个问题,我需要了解在远程数据获取的情况下使用响应式编程而不是 Promise 的优势是什么?

在哪些情况下(其他情况)使用反应性的东西比使用普通的东西更好?

【问题讨论】:

标签: javascript node.js angular reactive-programming rxjs


【解决方案1】:

基本上,如果您有一个异步事件,您不想收到有关(回调)的通知,您可以使用Promise。如果您预计会发生一系列事件,请使用Observable

Observable 相对于Promise 的优势

  • Observable 可以取消
  • Observable 是惰性的(在订阅之前不要做任何事情)
  • Observable 可以做 Promise 可以做的事情,但只有使用 Observable 才能让您以相同的方式编写代码(使用 rx 运算符而不是 .then(),无论您期待一个或一系列事件。

【讨论】:

  • 嗨!我知道这是一个古老的答案,但我可能不清楚一件事。 observables 是否可以为以后的订阅者保留返回值,类似于已经解决的承诺将立即成为.then()d?此外,您能否在不影响其操作的情况下拥有多个订阅者来订阅 observable(例如,进行两次异步调用)如果您认为值得提出自己的问题,我可以这样做。
  • BehaviorSubject 创建一个Observable,它会立即将最后一个值返回给新订阅者。 .share() 操作员进行Observable 多播,每个事件都传递给每个订阅者。注意 - 您需要显式导入运算符(如 mapshare、...)。
【解决方案2】:

@Günter 为您提供了 observables 的基础,尤其是调用 Promise 的能力。

更进一步,我认为 observables 的主要优势是能够使用运算符构建异步数据流/流。

以下是一些具体的用例:

  • debounceTime/switchMap。当您想利用表单输入根据相应的 HTTP 请求过滤列表时,您需要用于请求的值是用户完成写入时的值。不必发送多个请求:每个新字符一个(一个用于“s”,一个用于“so”,一个用于“som”,...,一个用于“搜索的东西”)。 debounceTime 运算符通过缓冲事件来实现这一点,并在一段时间不活动后提供最后一个事件。

    这是一个示例:

    @Component({
      (...)
      template: `
        <input [ngFormControl]="ctrl"/>
      `
    })
    export class MyComponent {
      constructor() {
        this.ctrl = new Control();
        this.ctrl.valueChanges
                   .debounceTime(500)
                   .distinctUntilChanged()
                   .switchMap((vallue: string) => {
                     // Get data according to the filled value
                     return this.service.getData(entry);
                   })
                   .subscribe(data => {
                     // Update the linked list
                     this.list = data;
                   });
      }
    }
    

    如果您只使用switchMap,则每个输入将有一个请求,但之前正在进行的请求将被取消。这可以让您获得正确的结果,尤其是在某些请求的请求执行时间较长的情况下。

    在这种情况下,您可以将 Web UI 中的事件(DOM 事件)链接到 HTTP 请求以相应地执行(对事件做出反应)并应用一些高级行为。

  • 实施重试。通过混合retryWhendelaytimeout 运算符,您可以轻松(且透明地)实现重试

    searchPlaces(searchText:string) {
      var params = new URLSearchParams();
      params.set('placename_startsWith', searchText);
      params.set('username', 'templth');
    
      return this.http.get('http://api.geonames.org/postalCodeSearchJSON',
          { search: params })
        .retryWhen(error => error.delay(500))
        .timeout(2000, return new Error('delay exceeded'))
        .map(res => res.json().postalCodes);
    }
    

我认为这就是 observables 的真正力量:异步处理链/数据流并基于事件链接应用程序的不同部分。这是使用 Promise 无法完成的事情,并且允许实现用例以使您的应用程序更加健壮。

这里有一系列文章可以为您提供更多详细信息:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-16
    • 1970-01-01
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多