I try to do a conditional mapping of several Observables. First I want to do a request to see if I need to get IP. If true, I get Ip before send Post Request.
Here is my 2 Observables:
// NEED IP
this.init$ = this.http.get(API_URL + '/init').pipe(
tap((response: any) => {
this.init_need_ip = response.need_ip
})
);
// IP WAN
this.ip_wan$ = this.http.get("https://api.ipify.org/?format=json").pipe(
tap((response: any) => { this.ip_wan = response.ip })
);
And my fonction:
getIp(model, url, params, options = {}): Observable<any> {
return this.init$.pipe(
concatMap(() => {
if (this.init_need_ip) {
this.ip_wan$;
}
}),
concatMap(() => {
return this.http.post<{model}>(url, JSON.stringify(Object.assign({}, params, {ip_wan: this.ip_wan, ip_lan: JSON.stringify(this.ip_lan)})), options);
}),
);
}
But I got an error:
Argument of type '() => void' is not assignable to parameter of type '(value: any, index: number) => ObservableInput'. Type 'void' is not assignable to type 'ObservableInput'.
If I try to return something in my else like:
return this.init$.pipe(
concatMap(() => {
if (this.init_need_ip) {
this.ip_wan$;
} else {
return of(null);
}
}),
concatMap(() => {
return this.http.post<{model}>(url, JSON.stringify(Object.assign({}, params, {ip_wan: this.ip_wan, ip_lan: JSON.stringify(this.ip_lan)})), options);
}),
);
I got another error from my service where the function is called:
TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
I would recommend passing data through the pipe, instead of assigning it to the component's properties, if they are not needed elsewhere.
If I understand your code correctly, I think you should be able to do something like this:
const init$ = this.http.get('/init');
const ip$ = this.http.get("https://api.ipify.org/?format=json");
init$.pipe(
switchMap(response => {
if(response.need_ip){
return ip$;
}else{
return of({})
}
}),
switchMap(response => {
return this.http.post<{model}>(
url,
JSON.stringify({
...params,
ip_wan: response.ip_wan,
ip_lan: JSON.stringify(this.ip_lan),
}),
options
);
})
)
Ideally tho, you should have a service with this API calls, and use it as follows:
this.ipService.init().pipe(
switchMap(response => response.need_ip ? this.ipService.getIp() : of({})),
switchMap(response => this.ipService.register(response.ip_wan, this.ip_lan))
)