我正在Angular 10中做一个Web应用程序。我尝试继续使用Observables而不是Promises,但是有时很难建立执行流程。
我想完成以下流程:
{isConfirmed: true}
),则显示一个载荷(此处是条件)。switchMap
以开始执行HTTP调用。逻辑:
send(title: string, message): Observable<any> {
const isConfirmed: Promise<{isConfirmed: boolean}> = this.alertService.warningConfirmation(
'Send message',
'Are you sure you want to send the message?',
'Send',
'Cancel'
);
return from(isConfirmed)
.pipe(
tap(res => res.isConfirmed ? this.loadingService.present() : EMPTY),
switchMap(res => from(this.service.httpCallOneGetUsers())
.pipe(
map(users => users.map(user => user.email)),
switchMap(emails => this.service.httpCallTwoSendMessage(title, message, emails))
)
),
finalize(() => this.loadingService.dismiss()),
tap({
next: () => console.log('Message sent!'),
error: () => console.log('Could not send the message.')
})
);
}
当我取消确认时,会触发错误事件。而且,永远不会显示加载。
我在第一个内部有2个HTTP调用switchMap
,两个都可能失败,一个返回Promise,另一个返回Observable。这就是为什么我在中添加了第一个HTTP调用的原因from()
。
我的目标是:
switchMap
如果确认结果为,则有条件执行/输入isConfirmed: true
。否则,请取消所有操作并退出逻辑而不会引发错误事件。tap
或finalize
隐藏负载并向用户显示成功/错误消息的最佳位置。
switchMap
如果确认结果为,则有条件执行/输入isConfirmed: true
。
尝试一下filter
。例如:
from(isConfirmed).pipe(
filter((res) => !!res.isConfirmed)
...
)
这只会发出与过滤条件匹配的值。
添加水龙头或敲定的完美位置在哪里?
finalize
:最后,因此,如果任何订阅在订阅之前失败,则将执行该订阅。
tap
:无论你要执行什么操作。例如,如果要打印用户o电子邮件,则需要将tap
说明放在管道中具有该数据的部分中。
总结:
from(isConfirmed).pipe(
filter((res) => !!res.isConfirmed),
switchMap((res) => from(this.service.httpCallOneGetUsers())),
map((users) => users.map((user) => user.email)),
switchMap((emails) =>
this.service.httpCallTwoSendMessage(title, message, emails)
),
finalize(() => this.loadingService.dismiss()),
tap({
next: () => console.log("Message sent!"),
error: () => console.log("Could not send the message."),
})
);
注意:last的tap
行为类似于订阅结果的接收者,这就是为什么last的原因。但是该代码应该放在中subscribe
。
要在不满足条件时最终确定 Observable 对象,你应该执行以下操作:
from(isConfirmed).pipe(
switchMap((res) => {
if (res.isConfirmed) {
this.loadingService.present();
return from(this.service.httpCallOneGetUsers());
} else {
throwError("");
}
}),
map((users) => users.map((user) => user.email)),
switchMap((emails) =>
this.service.httpCallTwoSendMessage(title, message, emails)
),
finalize(() => this.loadingService.dismiss()),
tap({
next: () => console.log("Message sent!"),
error: () => console.log("Could not send the message."),
})
);
如果条件为真,则管道将按预期顺序执行。如果条件为假,则从第一个条件switchMap
跳到finalize
。
在哪里添加表示加载的代码?也许在
filter
使用另一个之后switchMap
?另外,我也不了解filter
,您是说如果它的值是true
,流程将继续,如果是false
,则将调用tap
或finalize
?是的。表示加载与管道无关,因此请使用
tap
(就像不修改管道结果的外部执行一样)。如果过滤器匹配,则流程继续;否则,流程继续。如果不是,则不发出值(因此finalize
不会调用tap)@ RRGT19我已经用这种情况更新了我的答案