你为什么要在Observable函数上调用.call()?

时间:2017-12-04 04:04:08

标签: javascript angular rxjs observable ng-bootstrap

我是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(没有双关语)的阅读/观看,但我从来没有遇到过这样的事情。任何解释将不胜感激

3 个答案:

答案 0 :(得分:4)

我个人的意见是他们在RxJS 5.5之前使用它来引入可调运营商。 Angular在内部使用相同的样式。例如:https://github.com/angular/angular/blob/master/packages/router/src/router_preloader.ts#L91

原因是默认情况下他们必须使用rxjs/add/operators/XXX修补Observable类。这样做的缺点是某些第三方库正在修改一个可能意外导致应用程序中其他位置出现问题的全局对象。请参阅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类。

答案 1 :(得分:1)

要理解它,首先您可以查看预定义的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(事件可观察)

<强>已更新 示例代码: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);
  }
})

答案 2 :(得分:0)

我想

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