[英]ConcatMap is not executed in Rxjs
I am writing a file upload component.我正在写一个文件上传组件。 At first I check if a file exists and if so I prompt a user to either choose to save a copy or overwrite the existing file.
首先,我检查文件是否存在,如果存在,我会提示用户选择保存副本或覆盖现有文件。 After the existence check I want to upload the file, but if the user chooses to save as a copy the existence check has to be done again in a recursive manner.
存在性检查后我想上传文件,但如果用户选择另存为副本,则必须以递归方式再次进行存在性检查。 This means that it could and should happen that multiple observables are chained and executed one after another.
这意味着它可能而且应该发生多个可观察对象被链接起来并一个接一个地执行。
But here is the bug: The observable I return in the expression-function is not executed, although it is chained by the use of the concatMap
pipe.但这是一个错误:我在表达式函数中返回的可观察对象没有被执行,尽管它是通过使用
concatMap
pipe 链接起来的。
Why is this not behaving the way I intended it to behave?为什么这不符合我的预期?
The code looks like this:代码如下所示:
onDocumentsUploaded(documents: CustomDocument[]) {
console.log(documents)
documents = documents.map(document => {
return {
...document,
fullName: document.name + "." + document.extension
}
});
for (let document of documents) {
this.sub.add(
this.handleUpload(document).subscribe()
);
}
}
private handleUpload(document: CustomDocument): Observable<CustomDocument[]> {
return this.documentService.checkIfExists(document).pipe(
concatMap(exists => this.expression(document, exists))
);
}
private expression(document: CustomDocument, exists: boolean): Observable<CustomDocument[]> {
let subject$ = new Subject<CustomDocument[]>();
if (exists) {
this.confirmationService.confirm({
header: this.translate.instant("documentUpload.confirmation.header"),
message: this.translate.instant("documentUpload.confirmation.message", { fileName: "'" + document.fullName + "'" }),
icon: 'pi pi-info-circle',
accept: () => {
subject$.pipe(
concatMap(_ => this.handleUpload({
...document,
name: document.name + " (Copy)",
fullName: document.name + "(Copy)" + "." + document.extension
}).pipe(
tap(x => console.log("handleUpload"))
))
);
},
reject: () => {
subject$.pipe(
concatMap(_ => this.documentService.upload(document))
);
}
});
return subject$.asObservable();
}
else {
return this.documentService.upload(document);
}
}
In the function passed to accept
, you are pipeing the subject$
though the concatMap
, but you are ignoring the result observable.在传递给
accept
的 function 中,您将subject$
通过concatMap
进行管道传输,但您忽略了可观察到的结果。
Note that calling the .pipe()
does not modify the original observable (or subject) in any way, but rather creates a new observable with the operators applied.请注意,调用
.pipe()
不会以任何方式修改原始可观察对象(或主题),而是创建一个应用了运算符的新可观察对象。
I think that what you'd like to do here is to return the result of the subject$.pipe(...)
instead of the subject$.asObservable()
.我认为您想在这里做的是返回
subject$.pipe(...)
而不是subject$.asObservable()
的结果。
Based on your comment that the confirmationService.confirm
is thread blocking, the use of the Subject
in this case in unnecessary.根据您关于
confirmationService.confirm
是线程阻塞的评论,在这种情况下使用Subject
是不必要的。
You can do something like this instead.你可以做这样的事情。
private handleUpload(document: CustomDocument): Observable<CustomDocument> {
return this.documentService.checkIfExists(document).pipe(
concatMap((exists) =>
exists
? this.confirmAction(document)
: this.documentService.upload(document)
)
);
}
private confirmAction(document: CustomDocument): Observable<CustomDocument> {
//variable to save the 'result' of the confirm method
let action$: Observable<CustomDocument>;
this.confirmationService.confirm({
header: this.translate.instant("documentUpload.confirmation.header"),
message: this.translate.instant("documentUpload.confirmation.message", { fileName: "'" + document.fullName + "'" }),
icon: 'pi pi-info-circle',
accept: () => {
action$ = this.handleUpload({
...document,
name: document.name + " (Copy)",
fullName: document.name + "(Copy)" + "." + document.extension
})
},
reject: () => {
action$ = this.documentService.upload(document))
}
}
// since the confirm() is thread-blocking, the following return statement
// won't be executed until the confirm method completes.
return action$;
}
Btw the Subject
example wasn`t working for two main reasons.顺便说一句,
Subject
的例子没有工作主要有两个原因。
subject$.pipe()
does not modify the original subject$
, it creates a new observable.subject$.pipe()
不会修改原始subject$
,它会创建一个新的可观察对象。 So you were returning an incorrect source.Subject
you need to call to its method next
with the value.next
Subject
中发出通知,您需要使用该值调用它的方法。 (ie. subject$.next(value)
) subject$.next(value)
) But as I pointed out at the beginning in this case its use is not required and just overcomplicate the code.但正如我在开始时指出的那样,在这种情况下,它的使用不是必需的,只会使代码过于复杂。
Cheers干杯
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.