如何使用 switchmap 来避免 Angular 中的嵌套订阅?
How to use switchmap to avoid nested subscriptions in Angular?
我阅读了很多关于 switchmap 及其用途的内容,但是在订阅新数据时我没有看到很多示例。
所以我在我的 Angular 项目中使用了嵌套订阅,我想问你如何在我的示例中正确使用 switchmap 以更好地理解这个概念。
这是我的嵌套订阅:
this.sharedSrv.postDetail.subscribe(async post => {
if(post) {
this.hasPost = true;
this.post = post;
}
console.log(post);
this.viewedMainComment = null;
this.viewedSubComments = [];
this.userSrv.getUserAsObservable().subscribe(user => {
if(user){
if(this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id).subscribe(interaction => {
this.hasSubscribed = interaction["hasSubscribed"];
this.wasLiked = interaction["wasLiked"];
this.wasDisliked = interaction["wasDisliked"];
this.hasSaved = interaction["hasSaved"];
});
console.log(user);
this.isLoggedIn = true
} else {
this.isLoggedIn = false;
}
})
})
这里如何正确使用switchmap?
感谢任何帮助。
这里有很多事情需要注意
- 看起来外部可观察对象
this.sharedSrv.postDetail
和 this.userSrv.getUserAsObservable()
是不相关的。在这种情况下,您还可以使用 RxJS forkJoin
并行触发可观察对象。由于您要求 switchMap
,您可以尝试以下
import { of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
this.sharedSrv.postDetail.pipe(
switchMap(post => {
if (post) {
this.hasPost = true;
this.post = post;
}
console.log(post);
this.viewedMainComment = null;
this.viewedSubComments = [];
return this.userSrv.getUserAsObservable();
}),
switchMap(user => {
if (user) {
if (this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
console.log(user);
return this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id);
}
return of(null); // <-- emit `null` if `user` is undefined
})
).subscribe(
interaction => {
if(!!interaction) { // <-- only proceed if `interaction` is defined
this.hasSubscribed = interaction["hasSubscribed"];
this.wasLiked = interaction["wasLiked"];
this.wasDisliked = interaction["wasDisliked"];
this.hasSaved = interaction["hasSaved"];
this.isLoggedIn = true;
} else { // <-- set `isLoggedIn` to false if `user` was undefined
this.isLoggedIn = false;
}
}
);
- 我假设您正在使用
async
将 observable 转换为 promise。首先,除非绝对必要,否则我建议您不要混合使用 observables 和 promises。其次,您可以使用 RxJS from
函数将 observable 转换为 promise。
import { from, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
const obs$ = this.sharedSrv.postDetail.pipe(
switchMap(post => {
if (post) {
this.hasPost = true;
this.post = post;
}
console.log(post);
this.viewedMainComment = null;
this.viewedSubComments = [];
return this.userSrv.getUserAsObservable();
}),
switchMap(user => {
if (user) {
if (this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
console.log(user);
return this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id);
}
return of(null); // <-- emit `null` if `user` is undefined
})
);
from(obs$).then(
interaction => {
...
}
);
看起来像你想要的:
this.sharedSrv.postDetail.pipe(
switchMap(post => {
if (post) {
this.hasPost = true;
this.post = post;
}
console.log(post);
this.viewedMainComment = null;
this.viewedSubComments = [];
return this.userSrv.getUserAsObservable();
}),
swtichMap(user => {
this.isLoggedIn = false;
if (user) {
if (this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
this.isLoggedIn = true;
console.log(user);
return this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id);
} else {
return of(null);
}
}).subscribe(interaction => {
if (!interaction) return;
this.hasSubscribed = interaction["hasSubscribed"];
this.wasLiked = interaction["wasLiked"];
this.wasDisliked = interaction["wasDisliked"];
this.hasSaved = interaction["hasSaved"];
})
);
要转换 Observables
,您需要使用 piping
即在可观察对象上调用 pipe()
方法并传入 rxjs
转换运算符
我们可以将您的代码转换为的示例
this.sharedSrv.postDetail.pipe(
switchMap(post => {
if(post) {
this.hasPost = true;
this.post = post;
}
this.viewedMainComment = null;
this.viewedSubComments = [];
return this.userSrv.getUserAsObservable())
}),
switchMap(
user => {
if(user) {
if(this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
return this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id)
} else {
this.isLoggedIn = false;
return of (null) // You need import { of } from 'rxjs'
}
}
)),
tap( interaction => {
if(interaction) {
this.hasSubscribed = interaction["hasSubscribed"];
this.wasLiked = interaction["wasLiked"];
this.wasDisliked = interaction["wasDisliked"];
this.hasSaved = interaction["hasSaved"];
}
})
).subscribe()
我阅读了很多关于 switchmap 及其用途的内容,但是在订阅新数据时我没有看到很多示例。 所以我在我的 Angular 项目中使用了嵌套订阅,我想问你如何在我的示例中正确使用 switchmap 以更好地理解这个概念。
这是我的嵌套订阅:
this.sharedSrv.postDetail.subscribe(async post => {
if(post) {
this.hasPost = true;
this.post = post;
}
console.log(post);
this.viewedMainComment = null;
this.viewedSubComments = [];
this.userSrv.getUserAsObservable().subscribe(user => {
if(user){
if(this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id).subscribe(interaction => {
this.hasSubscribed = interaction["hasSubscribed"];
this.wasLiked = interaction["wasLiked"];
this.wasDisliked = interaction["wasDisliked"];
this.hasSaved = interaction["hasSaved"];
});
console.log(user);
this.isLoggedIn = true
} else {
this.isLoggedIn = false;
}
})
})
这里如何正确使用switchmap? 感谢任何帮助。
这里有很多事情需要注意
- 看起来外部可观察对象
this.sharedSrv.postDetail
和this.userSrv.getUserAsObservable()
是不相关的。在这种情况下,您还可以使用 RxJSforkJoin
并行触发可观察对象。由于您要求switchMap
,您可以尝试以下
import { of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
this.sharedSrv.postDetail.pipe(
switchMap(post => {
if (post) {
this.hasPost = true;
this.post = post;
}
console.log(post);
this.viewedMainComment = null;
this.viewedSubComments = [];
return this.userSrv.getUserAsObservable();
}),
switchMap(user => {
if (user) {
if (this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
console.log(user);
return this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id);
}
return of(null); // <-- emit `null` if `user` is undefined
})
).subscribe(
interaction => {
if(!!interaction) { // <-- only proceed if `interaction` is defined
this.hasSubscribed = interaction["hasSubscribed"];
this.wasLiked = interaction["wasLiked"];
this.wasDisliked = interaction["wasDisliked"];
this.hasSaved = interaction["hasSaved"];
this.isLoggedIn = true;
} else { // <-- set `isLoggedIn` to false if `user` was undefined
this.isLoggedIn = false;
}
}
);
- 我假设您正在使用
async
将 observable 转换为 promise。首先,除非绝对必要,否则我建议您不要混合使用 observables 和 promises。其次,您可以使用 RxJSfrom
函数将 observable 转换为 promise。
import { from, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
const obs$ = this.sharedSrv.postDetail.pipe(
switchMap(post => {
if (post) {
this.hasPost = true;
this.post = post;
}
console.log(post);
this.viewedMainComment = null;
this.viewedSubComments = [];
return this.userSrv.getUserAsObservable();
}),
switchMap(user => {
if (user) {
if (this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
console.log(user);
return this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id);
}
return of(null); // <-- emit `null` if `user` is undefined
})
);
from(obs$).then(
interaction => {
...
}
);
看起来像你想要的:
this.sharedSrv.postDetail.pipe(
switchMap(post => {
if (post) {
this.hasPost = true;
this.post = post;
}
console.log(post);
this.viewedMainComment = null;
this.viewedSubComments = [];
return this.userSrv.getUserAsObservable();
}),
swtichMap(user => {
this.isLoggedIn = false;
if (user) {
if (this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
this.isLoggedIn = true;
console.log(user);
return this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id);
} else {
return of(null);
}
}).subscribe(interaction => {
if (!interaction) return;
this.hasSubscribed = interaction["hasSubscribed"];
this.wasLiked = interaction["wasLiked"];
this.wasDisliked = interaction["wasDisliked"];
this.hasSaved = interaction["hasSaved"];
})
);
要转换 Observables
,您需要使用 piping
即在可观察对象上调用 pipe()
方法并传入 rxjs
转换运算符
我们可以将您的代码转换为的示例
this.sharedSrv.postDetail.pipe(
switchMap(post => {
if(post) {
this.hasPost = true;
this.post = post;
}
this.viewedMainComment = null;
this.viewedSubComments = [];
return this.userSrv.getUserAsObservable())
}),
switchMap(
user => {
if(user) {
if(this.post.user.id == user.id) this.isOwnPost = true;
this.user = user;
return this.postsSrv.getPostInteraction(this.user.id, this.post.id, this.post.user.id)
} else {
this.isLoggedIn = false;
return of (null) // You need import { of } from 'rxjs'
}
}
)),
tap( interaction => {
if(interaction) {
this.hasSubscribed = interaction["hasSubscribed"];
this.wasLiked = interaction["wasLiked"];
this.wasDisliked = interaction["wasDisliked"];
this.hasSaved = interaction["hasSaved"];
}
})
).subscribe()