简体   繁体   English

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

[英]Why would you ever call .call() on Observable functions?

I am a relative beginner in Angular, and I am struggling to understand some source I am reading from the ng-bootstrap project. 我是Angular的相对初学者,我正在努力了解我从ng-bootstrap项目中读取的一些资源。 The source code can be found here . 源代码可以在这里找到

I am very confused by the code in ngOnInit: 我对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$);
  }

What is the point of calling .call(...) on these Observable functions? 在这些Observable函数上调用.call(...)什么意义? What kind of behaviour is this trying to achieve? 试图达到什么样的行为? Is this a normal pattern? 这是正常模式吗?

I've done a lot of reading/watching about Observables (no pun intended) as part of my Angular education but I have never come across anything like this. 在我的Angular教育中,我已经做了大量关于Observables的阅读/观看(无双关语),但是我从未遇到过这样的事情。 Any explanation would be appreciated 任何解释将不胜感激

My personal opinion is that they were using this for RxJS prior 5.5 which introduced lettable operators. 我个人的看法是,他们在RxJS 5.5之前的版本中使用了它,引入了可操作的运算符。 The same style is used internally by Angular. Angular内部使用相同的样式。 For example: https://github.com/angular/angular/blob/master/packages/router/src/router_preloader.ts#L91 . 例如: https : //github.com/angular/angular/blob/master/packages/router/src/router_preloader.ts#L91

The reason for this is that by default they would have to patch the Observable class with rxjs/add/operators/XXX . 原因是默认情况下,他们必须使用rxjs/add/operators/XXX修补Observable类。 The disadvantage of this is that some 3rd party library is modifying a global object that might unexpectedly cause problems somewhere else in your app. 这样做的缺点是某些第三方库正在修改全局对象,该对象可能会意外导致应用程序其他地方出现问题。 See https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md#why . 参见https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md#why

You can see at the beginning of the file that they import each operator separately https://github.com/ng-bootstrap/ng-bootstrap/blob/master/src/typeahead/typeahead.ts#L22-L25 . 您可以在文件开头看到他们分别导入每个运算符https://github.com/ng-bootstrap/ng-bootstrap/blob/master/src/typeahead/typeahead.ts#L22-L25

So by using .call() they can use any operator and still avoid patching the Observable class. 因此,通过使用.call()他们可以使用任何运算符,并且仍然避免修补Observable类。

To understand it, first you can have a look at the predefined JavaScript function method "call": 要了解它,首先您可以看一下预定义的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"

The reason of calling "call" is to invoke a function in object "person" and pass the context to it "myObject". 调用“ call”的原因是在对象“ person”中调用一个函数并将上下文传递给它“ myObject”。

Similarly, the reason of this calling "call" below: 类似地,此之所以称为“通话”的原因如下:

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

is providing the context "this._valueChanges", but also provide the function to be called base on that context, that is the second parameter, the anonymous function 在提供上下文“ this._valueChanges”的同时,还提供了基于该上下文被调用的函数,即第二个参数,即匿名函数

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

In the example that you're using: 在您使用的示例中:

  • this._valueChanges is the Input Event Observerable this._valueChanges是可观察到的输入事件

  • The _do.call is for doing some side affects whenever the event input happens, then it returns a mirrored Observable of the source Observable (the event observable) _do.call用于在事件输入发生时产生一些副作用,然后它返回源Observable的镜像Observable(事件Observable)

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

About the do calling: 关于do调用:

You can call it on an Observable like this: 您可以像这样在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));

In this case you don't have to pass the first parameter as the context "Observable". 在这种情况下,您不必将第一个参数作为上下文“可观察”传递。

But when you call it from its own place like you said, you need to pass the first parameter as the "Observable" that you want to call on. 但是,当像您所说的那样从自己的位置调用它时,您需要将第一个参数作为要调用的“可观察”传递。 That's the different. 那是不同的。

as @Fan Cheung mentioned, if you don't want to call it from its own place, you can do it like: 正如@Fan Cheung所提到的,如果您不想在自己的地方调用它,则可以执行以下操作:

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

I suppose 我想

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

is equivalent to 相当于

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

In my opinion it's not an usual pattern(I think it is the same pattern but written in different fashion) for working with observable. 在我看来,使用可观察对象并不是通常的模式(我认为这是相同的模式,但是写法不同)。 _do() in the code is being used as standalone function take a callback as argument and required to be binded to the scope of the source Observable 代码中的_do()用作独立函数,以回调作为参数,并且需要绑定到源Observable的范围

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM