【问题标题】:Why would you ever call .call() on Observable functions?为什么你会在 Observable 函数上调用 .call() ?
【发布时间】:2018-05-17 12:04:30
【问题描述】:

我是 Angular 的相对初学者,我正在努力理解我从 ng-bootstrap 项目中阅读的一些源代码。 The source code can be found here

我对 ngOnInit 中的代码很困惑:

ngOnInit(): void {
    const inputValues$ = _do.call(this._valueChanges, value => {
      this._userInput = value;
      if (this.editable) {
        this._onChange(value);
      }
    });
    const results$ = letProto.call(inputValues$, this.ngbTypeahead);
    const processedResults$ = _do.call(results$, () => {
      if (!this.editable) {
        this._onChange(undefined);
      }
    });
    const userInput$ = switchMap.call(this._resubscribeTypeahead, () => processedResults$);
    this._subscription = this._subscribeToUserInput(userInput$);
  }

在这些 Observable 函数上调用 .call(...) 有什么意义?这是试图实现什么样的行为?这是正常模式吗?

作为我 Angular 教育的一部分,我已经阅读/观看了很多关于 Observables(不是双关语)的内容,但我从未遇到过这样的事情。任何解释将不胜感激

【问题讨论】:

    标签: javascript angular rxjs observable ng-bootstrap


    【解决方案1】:

    我个人的看法是,他们在 5.5 之前的 RxJS 中使用了这个,它引入了 lettable 运算符。 Angular 内部使用了相同的样式。例如:https://github.com/angular/angular/blob/master/packages/router/src/router_preloader.ts#L91

    这样做的原因是默认情况下他们必须使用rxjs/add/operators/XXX 修补 Observable 类。这样做的缺点是某些 3rd 方库正在修改一个全局对象,这可能会意外地在您的应用程序的其他地方引起问题。见https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md#why

    您可以在文件的开头看到它们分别导入每个运算符https://github.com/ng-bootstrap/ng-bootstrap/blob/master/src/typeahead/typeahead.ts#L22-L25

    因此,通过使用.call(),他们可以使用任何运算符,并且仍然避免修补Observable 类。

    【讨论】:

      【解决方案2】:

      要理解它,首先可以看一下预定义的JavaScript函数方法“call”:

      var person = {
          firstName:"John",
          lastName: "Doe",
          fullName: function() {
              return this.firstName + " " + this.lastName;
          }
      }
      var myObject = {
          firstName:"Mary",
          lastName: "Doe",
      }
      person.fullName.call(myObject);  // Will return "Mary Doe"
      

      调用“call”的原因是调用对象“person”中的一个函数并将上下文传递给它“myObject”。

      同样,下面这个调用“调用”的原因:

      const inputValues$ = _do.call(this._valueChanges, value => {
        this._userInput = value;
        if (this.editable) {
          this._onChange(value);
        }
      });
      

      在提供上下文“this._valueChanges”的同时,还提供了基于该上下文调用的函数,即第二个参数,匿名函数

      value => {
        this._userInput = value;
        if (this.editable) {
          this._onChange(value);
        }
      }
      

      在您使用的示例中:

      • this._valueChanges 是可观察的输入事件

      • _do.call 用于在事件输入发生时做一些副作用,然后它返回源 Observable(事件 observable)的镜像 Observable

      更新 示例代码:https://plnkr.co/edit/dJNRNI?p=preview

      关于do调用:

      你可以像这样在 Observable 上调用它:

      const source = Rx.Observable.of(1,2,3,4,5);
      const example = source
      .do(val => console.log(`BEFORE MAP: ${val}`))
      .map(val => val + 10)
      .do(val => console.log(`AFTER MAP: ${val}`));
      const subscribe = example.subscribe(val => console.log(val));
      

      在这种情况下,您不必将第一个参数作为上下文“Observable”传递。

      但是当你像你说的那样从它自己的地方调用它时,你需要将第一个参数作为你想要调用的“Observable”传递。那是不一样的。

      正如@Fan Cheung 提到的,如果你不想从它自己的地方调用它,你可以这样做:

      const inputValues$=this._valueChanges.do(value=>{
        this._userInput = value;
        if (this.editable) {
          this._onChange(value);
        }
      })
      

      【讨论】:

      • 令人困惑的是,do 通常在 Observable 上被调用,而不仅仅是我们的无处可寻。这个答案并没有让我更清楚
      • "Do" 在 Observable 上被调用,因为: Observable 是一个事件流,当我们在其上调用 "do" 时,这意味着它订阅该事件以在事件触发时做任何想做的事情.
      • 我有一个例子给你:plnkr.co/edit/dJNRNI?p=preview。运行一下就可以在控制台上看的更清楚了
      • 很高兴它有帮助:)
      【解决方案3】:

      我想

      const inputValues$ = _do.call(this._valueChanges, value => {
        this._userInput = value;
        if (this.editable) {
          this._onChange(value);
        }
      }); 
      

      等价于

      const inputValues$=this._valueChanges.do(value=>{
       this._userInput = value;
        if (this.editable) {
          this._onChange(value);
        }
      })
      

      在我看来,这不是使用 observable 的常用模式(我认为它是相同的模式,但以不同的方式编写)。代码中的 _do() 被用作独立函数,将回调作为参数,并且需要绑定到源 Observable 的范围

      https://github.com/ReactiveX/rxjs/blob/master/src/operator/do.ts

      【讨论】:

        猜你喜欢
        • 2020-10-10
        • 1970-01-01
        • 2010-10-06
        • 2018-05-10
        • 2015-02-17
        • 1970-01-01
        • 2012-01-01
        • 1970-01-01
        • 2019-02-11
        相关资源
        最近更新 更多