使用 angular http 模块时应该使用 map 还是 switchmap?
Should I use map or switchmap when using angular http module?
我在 angular 应用程序中使用了以下代码。我使用 RxJS map
调用类似于数组 map
的使用方式。在阅读了 RxJS switchmap
运算符之后,我不确定我应该使用 map
还是 switchmap
。我应该使用 switchmap
以便关闭从 http
调用返回的可观察对象,从而不会发生内存泄漏吗?
getPeopleForTypeahead(term: string): Observable<IPersonForTypeahead[]> {
var peopleUrl = `https://localhost:5001/api/peoplesearch?name=${term}`;
return this.http.get<any>(peopleUrl)
.pipe(
map(pl => {
return this.peopleAsFlattened(pl.peopleList).reduce((p, c) => p.concat(c));
}),
catchError(this.handleError('getPeopleForTypeahead', []))
);
}
peopleAsFlattened = (pla: IPeopleList[]) => {
return pla.map(pl => pl.people.map(p => {
return {
id: p.id,
fullName: p.fullNames[0].firstName + " " + p.fullNames[0].lastName
};
}));
}
当源 Observable 是热 Observable 时,我们使用 switchMap
。在这种情况下,您更喜欢在 source 发出时取消后续 observable 的行为。
在您的代码中,您的来源是一个 one-off http 调用,这意味着它不会发出多次并且后续操作不是执行可观察的而是改变数组。不需要使用switchMap
switchMap
不能与 map
运算符互换,反之亦然。尽管它们都与映射有关(顾名思义),但它们有两个独立的 use-cases.
在您的特定情况下,map
运算符是可行的方法。
何时使用 switchMap
?
当您检查所有这些要求时,您只能使用 switchMap(cb)
:
您的回调函数 cb
传递到 switchMap
return 一个可观察对象 observable$
。
如果您的 cb
(回调函数)没有 return 可观察值,您应该查看不处理 higher-level 可观察值的运算符,例如 filter
和 map
(你实际需要的); not 处理 higher-level 可观察值的运算符,例如 concatMap
以及 switchMap
.
您想在管道中的下一个操作(switchMap
之后)执行之前按顺序执行 cb
。
也许你想运行逻辑在cb
里面,有选择的在执行后得到cb
的return值,这样你就可以把它传下去例如,用于进一步处理的管道。
当你想“丢弃”cb
的执行和 re-execute cb
每次源可观察时会发生什么(滴流的东西下降到 switchMap(cb)
) 发出一个新的 value/notification.
应用我们希望学到的知识,我们知道您的 cb
:
pl => {
return this.peopleAsFlattened(pl.peopleList).reduce((p, c) => p.concat(c));
}
returns 一个普通的 JavaScript 数组;不是可观察的。这使使用 switchMap
成为不可能,因为它违反了我在上面提出的第一个要求。
希望这是有道理的。 :)
map
和 switchMap
的用途完全不同:
map
- 变换发射的形状
switchMap
- 订阅一个 observable 并将其发射到流中
map
当您想要变换每个发射的形状时使用map
。例如:发出用户名 属性,而不是整个用户对象:
userName$: Observable<string> = this.service.getUser(123).pipe(
map(user => user.name)
);
switchMap
当您想要将发射映射到另一个可观察对象并发射其发射时,请使用 switchMap
。例如:您有一些 id
的可观察对象,并希望在获取资源后发出资源:
user$: Observable<User> = this.userId$.pipe(
switchMap(id => this.service.getUser(id)),
);
订阅 user$
时,会发出从 service.getUser(id)
返回的用户( 不是用户 ID 字符串 )。
我在 angular 应用程序中使用了以下代码。我使用 RxJS map
调用类似于数组 map
的使用方式。在阅读了 RxJS switchmap
运算符之后,我不确定我应该使用 map
还是 switchmap
。我应该使用 switchmap
以便关闭从 http
调用返回的可观察对象,从而不会发生内存泄漏吗?
getPeopleForTypeahead(term: string): Observable<IPersonForTypeahead[]> {
var peopleUrl = `https://localhost:5001/api/peoplesearch?name=${term}`;
return this.http.get<any>(peopleUrl)
.pipe(
map(pl => {
return this.peopleAsFlattened(pl.peopleList).reduce((p, c) => p.concat(c));
}),
catchError(this.handleError('getPeopleForTypeahead', []))
);
}
peopleAsFlattened = (pla: IPeopleList[]) => {
return pla.map(pl => pl.people.map(p => {
return {
id: p.id,
fullName: p.fullNames[0].firstName + " " + p.fullNames[0].lastName
};
}));
}
当源 Observable 是热 Observable 时,我们使用 switchMap
。在这种情况下,您更喜欢在 source 发出时取消后续 observable 的行为。
在您的代码中,您的来源是一个 one-off http 调用,这意味着它不会发出多次并且后续操作不是执行可观察的而是改变数组。不需要使用switchMap
switchMap
不能与 map
运算符互换,反之亦然。尽管它们都与映射有关(顾名思义),但它们有两个独立的 use-cases.
在您的特定情况下,map
运算符是可行的方法。
何时使用 switchMap
?
当您检查所有这些要求时,您只能使用 switchMap(cb)
:
您的回调函数
cb
传递到switchMap
return 一个可观察对象observable$
。如果您的
cb
(回调函数)没有 return 可观察值,您应该查看不处理 higher-level 可观察值的运算符,例如filter
和map
(你实际需要的); not 处理 higher-level 可观察值的运算符,例如concatMap
以及switchMap
.您想在管道中的下一个操作(
switchMap
之后)执行之前按顺序执行cb
。也许你想运行逻辑在
cb
里面,有选择的在执行后得到cb
的return值,这样你就可以把它传下去例如,用于进一步处理的管道。当你想“丢弃”
cb
的执行和 re-executecb
每次源可观察时会发生什么(滴流的东西下降到switchMap(cb)
) 发出一个新的 value/notification.
应用我们希望学到的知识,我们知道您的 cb
:
pl => {
return this.peopleAsFlattened(pl.peopleList).reduce((p, c) => p.concat(c));
}
returns 一个普通的 JavaScript 数组;不是可观察的。这使使用 switchMap
成为不可能,因为它违反了我在上面提出的第一个要求。
希望这是有道理的。 :)
map
和 switchMap
的用途完全不同:
map
- 变换发射的形状switchMap
- 订阅一个 observable 并将其发射到流中
map
当您想要变换每个发射的形状时使用map
。例如:发出用户名 属性,而不是整个用户对象:
userName$: Observable<string> = this.service.getUser(123).pipe(
map(user => user.name)
);
switchMap
当您想要将发射映射到另一个可观察对象并发射其发射时,请使用 switchMap
。例如:您有一些 id
的可观察对象,并希望在获取资源后发出资源:
user$: Observable<User> = this.userId$.pipe(
switchMap(id => this.service.getUser(id)),
);
订阅 user$
时,会发出从 service.getUser(id)
返回的用户( 不是用户 ID 字符串 )。