使用 mergeMap 合并 Angular 中的两个顺序订阅时出错
Getting Error when using mergeMap to merge two sequential subscriptions in Angular
我有两个连续订阅:
this.authService.tokenObs.pipe( map(res => res),mergeMap( token =>
this.service.getUsers(token).subscribe(res2=>{
console.log('res2', res2)
})
));
我在合并映射中遇到令牌参数错误:
Argument of type '(token: {}) => Subscription' is not assignable to
parameter of type '(value: {}, index: number) => ObservableInput<{}>'.
Type 'Subscription' is not assignable to type 'ObservableInput<{}>'.
Type 'Subscription' is not assignable to type 'ArrayLike<{}>'.
Property 'length' is missing in type 'Subscription'. (parameter) token: {}
我是第一次使用 mergeMap,所以不熟悉这个错误。
您需要像下面这样修改您的代码
this.authService.tokenObs.pipe(
map(res => res),
mergeMap(this.service.getUsers(token))
).subscribe(res2=>{
console.log('res2', res2)
});
由于您是新手,能否看一下工作示例https://stackblitz.com/edit/angular-gsefpz
import { Component } from '@angular/core';
import { map, mergeMap } from 'rxjs/operators';
import { HttpClient} from '@angular/common/http';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular';
constructor(public http: HttpClient) {
this.http.get('https://jsonplaceholder.typicode.com/users').pipe(
map(res => res[0].id),
mergeMap(id => this.http.get(`https://jsonplaceholder.typicode.com/posts?userId=${id}`))
).subscribe(res2 => {
console.log('res2', res2)
});
}
}
编辑 2:
https://stackblitz.com/edit/angular-gsefpz
更新了处理错误的代码。测试你把它改成错误的错误案例url。
import { Component } from '@angular/core';
import { map, mergeMap, tap, catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular';
constructor(public http: HttpClient) {
this.http.get('https://jsonplaceholder.typicode.com/users').pipe(
tap(data => console.log('data >>> ', data)),
map(res => res[0].id),
tap(data => console.log('transformed data >>> ', data)),
mergeMap(id => this.http.get(`https://jsonplaceholder.typicode.com/posts?userId=${id}`)),
catchError(error => {
console.log('ERROR >>>> ', JSON.stringify(error));
return throwError({ status: error.status, errorMsg: error.statusText });
})
).subscribe(res2 => { console.log('res2', res2) }, err => console.log(err));
}
}
编辑 3
对于 rxjs 5.5
https://stackblitz.com/edit/angular-5-tutorial-yzowvt
import { Component } from '@angular/core';
import {HttpClient} from '@angular/common/http';
import { Observable } from 'rxjs';
constructor(public http: HttpClient) {
this.http.get('https://jsonplaceholder.typicode.com/users')
.do(data => console.log('data >>> ', data))
.map(res => res[0].id)
.do(data => console.log('transformed data >>> ', data))
.mergeMap(id => this.http.get(`https://jsonplaceholder.typicode.com/posts?userId=${id}`))
.catch(error => {
console.log('ERROR >>>> ', JSON.stringify(error));
return Observable.throw({ status: error.status, errorMsg: error.statusText });
})
.subscribe(res2 => { console.log('res2', res2) }, err => console.log(err));
}
如果你想使用相互依赖的 Observable 序列,你最好使用 "switchMap":
import { switchMap } from 'rxjs/operators';
this.authService.tokenObs.pipe(
switchMap((token) => {
return this.service.getUsers(token);
}),
map((user) => {
// do what you want;
})
)
您也可以使用 "mergeMap":
import { mergeMap} from 'rxjs/operators';
this.authService.tokenObs.pipe(
mergeMap((token) => {
return this.service.getUsers(token);
}),
map((user) => {
// do what you want;
})
)
不同的是,如果this.authService.tokenObs发生变化,"switchMap"会取消对服务器的未决请求(this.service.getUsers(token))。但是"mergeMap"不会取消,而是继续执行。
P.S:尝试研究并开始使用@ngrx-store 以获得更好的带有 Observables 的系统架构:https://github.com/ngrx/platform
我有两个连续订阅:
this.authService.tokenObs.pipe( map(res => res),mergeMap( token =>
this.service.getUsers(token).subscribe(res2=>{
console.log('res2', res2)
})
));
我在合并映射中遇到令牌参数错误:
Argument of type '(token: {}) => Subscription' is not assignable to
parameter of type '(value: {}, index: number) => ObservableInput<{}>'.
Type 'Subscription' is not assignable to type 'ObservableInput<{}>'.
Type 'Subscription' is not assignable to type 'ArrayLike<{}>'.
Property 'length' is missing in type 'Subscription'. (parameter) token: {}
我是第一次使用 mergeMap,所以不熟悉这个错误。
您需要像下面这样修改您的代码
this.authService.tokenObs.pipe(
map(res => res),
mergeMap(this.service.getUsers(token))
).subscribe(res2=>{
console.log('res2', res2)
});
由于您是新手,能否看一下工作示例https://stackblitz.com/edit/angular-gsefpz
import { Component } from '@angular/core';
import { map, mergeMap } from 'rxjs/operators';
import { HttpClient} from '@angular/common/http';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular';
constructor(public http: HttpClient) {
this.http.get('https://jsonplaceholder.typicode.com/users').pipe(
map(res => res[0].id),
mergeMap(id => this.http.get(`https://jsonplaceholder.typicode.com/posts?userId=${id}`))
).subscribe(res2 => {
console.log('res2', res2)
});
}
}
编辑 2:
https://stackblitz.com/edit/angular-gsefpz
更新了处理错误的代码。测试你把它改成错误的错误案例url。
import { Component } from '@angular/core';
import { map, mergeMap, tap, catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = 'Angular';
constructor(public http: HttpClient) {
this.http.get('https://jsonplaceholder.typicode.com/users').pipe(
tap(data => console.log('data >>> ', data)),
map(res => res[0].id),
tap(data => console.log('transformed data >>> ', data)),
mergeMap(id => this.http.get(`https://jsonplaceholder.typicode.com/posts?userId=${id}`)),
catchError(error => {
console.log('ERROR >>>> ', JSON.stringify(error));
return throwError({ status: error.status, errorMsg: error.statusText });
})
).subscribe(res2 => { console.log('res2', res2) }, err => console.log(err));
}
}
编辑 3 对于 rxjs 5.5 https://stackblitz.com/edit/angular-5-tutorial-yzowvt
import { Component } from '@angular/core';
import {HttpClient} from '@angular/common/http';
import { Observable } from 'rxjs';
constructor(public http: HttpClient) {
this.http.get('https://jsonplaceholder.typicode.com/users')
.do(data => console.log('data >>> ', data))
.map(res => res[0].id)
.do(data => console.log('transformed data >>> ', data))
.mergeMap(id => this.http.get(`https://jsonplaceholder.typicode.com/posts?userId=${id}`))
.catch(error => {
console.log('ERROR >>>> ', JSON.stringify(error));
return Observable.throw({ status: error.status, errorMsg: error.statusText });
})
.subscribe(res2 => { console.log('res2', res2) }, err => console.log(err));
}
如果你想使用相互依赖的 Observable 序列,你最好使用 "switchMap":
import { switchMap } from 'rxjs/operators';
this.authService.tokenObs.pipe(
switchMap((token) => {
return this.service.getUsers(token);
}),
map((user) => {
// do what you want;
})
)
您也可以使用 "mergeMap":
import { mergeMap} from 'rxjs/operators';
this.authService.tokenObs.pipe(
mergeMap((token) => {
return this.service.getUsers(token);
}),
map((user) => {
// do what you want;
})
)
不同的是,如果this.authService.tokenObs发生变化,"switchMap"会取消对服务器的未决请求(this.service.getUsers(token))。但是"mergeMap"不会取消,而是继续执行。 P.S:尝试研究并开始使用@ngrx-store 以获得更好的带有 Observables 的系统架构:https://github.com/ngrx/platform