Why did you ever call .call () in the Observable function?

I'm a relative newbie to Angular, and I'm struggling to figure out the source I'm reading from the ng-bootstrap project. Source code can be found here .

I am very confused by the code in 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 .call(...) for these observable functions? What kind of behavior is this trying to achieve? Is this a normal picture?

I read / watched a lot of Observables (not a pun) as part of my Angular training, but I never came across anything like that. Any explanation would be appreciated.

+8
javascript angular observable rxjs ng-bootstrap
source share
3 answers

To understand this, first you can take a look at the predefined method of the JavaScript call function:

 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 for calling the "call" is the function call in the "person" object and the transfer of the context into it "myObject".

Similarly, the reason for this call is β€œcall” below:

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

provides the context "this._valueChanges", but also provides a function that will be called the base in this context, that is, the second parameter, an anonymous function

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

In the example you use:

  • this._valueChanges is an Observerable input event

  • _do.call is intended to perform some side effects each time the event is input, then it will return a mirror image of the observed source Observable (observed event)

UPDATED Code example: https://plnkr.co/edit/dJNRNI?p=preview

About the do call:

You can call it observable as follows:

 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 do not need to pass the first parameter as an Observed context.

But when you call it from your place, as you said, you need to pass the first parameter as the β€œObservable” that you want to call. It is different.

as @Fan Cheung pointed out, if you don't want to call it from your place, you can do it like this:

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

My personal opinion is that they used this for RxJS prior to 5.5, which introduced lettable statements. The same style is used inside Angular. For example: https://github.com/angular/angular/blob/master/packages/router/src/router_preloader.ts#L91 .

The reason for this is that by default they will need to fix the Observable class with rxjs/add/operators/XXX . The disadvantage of this is that some third-party library modifies the global object, which can unexpectedly cause problems elsewhere in the application. See https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md#why .

At the beginning of the file, you can see that they import each statement separately https://github.com/ng-bootstrap/ng-bootstrap/blob/master/src/typeahead/typeahead.ts#L22-L25 .

Thus, using .call() , they can use any operator and still not use the Observable patch.

+4
source share

Let's pretend that

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

equivalently

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

In my opinion, this is not an ordinary template (I think it is the same template, but written in different ways) to work with the observable. _do () in the code is used as a standalone function, performs a callback as an argument, and must be bound to the Observable source area

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

0
source share

All Articles