Javascript concatMap无法处理数组中的所有项
我正在处理一系列文件。对于每个文件,我需要请求正确的上载URL,然后将该文件上载到其正确的端点Javascript concatMap无法处理数组中的所有项,javascript,rxjs,Javascript,Rxjs,我正在处理一系列文件。对于每个文件,我需要请求正确的上载URL,然后将该文件上载到其正确的端点 concatMap应仅在上一个值完成后发出。这样,文件应该按顺序处理 这是我的密码: filesChanged(e) { const files_raw = e.srcElement.files; of(files_raw) .pipe( flatMap((file) => file), tap((file) => console.log("Firing 1", file)),
concatMap
应仅在上一个值完成后发出。这样,文件应该按顺序处理
这是我的密码:
filesChanged(e) {
const files_raw = e.srcElement.files;
of(files_raw)
.pipe(
flatMap((file) => file),
tap((file) => console.log("Firing 1", file)),
concatMap((file) => {
return this.ms.fetchUploadURL().pipe(withLatestFrom(of(file)));
}),
tap((file) => console.log("Firing 2", file)),
concatMap((values) => {
return this.ms.uploadDirectToS3(values[0], values[1])
.pipe(tap(value => console.log('From request', value)), withLatestFrom(of(values[0])));
})
)
.subscribe(event => {
console.log('In Subscribe', event);
});
}
如果我尝试上载4个文件,此代码将向控制台记录以下输出:
开火1
开火1
开火1
开火1
射击2
根据要求
订阅
换句话说,只处理和上载第一个文件。所有其他文件似乎都被忽略了。为什么会这样?
当第一个URL完成后,它不应该开始获取第二个URL吗
另外,如果我将
concatMap
更改为mergeMap
,那么它确实可以工作,但它同时处理所有文件,而不是按顺序处理。我认为将并发选项传递给mergeMap
可能会有所帮助,但其作用与concatMap相同 首先,我尝试在这里模拟您的案例:。
请注意,我使用的是mergeMap
而不是flatMap
,但它们完全相同
根据这样的模拟和我看到的实现的逻辑,您得到的是有意义的,并且您可能只看到1次“触发2”,因为在第二次调用uploadDirectToS3
时发生了一些错误。也许您应该像上面的模拟一样,向subscribe
添加一个错误函数
尽管如此,我想您应该在代码中添加一些更正,以获得所需的内容
让我们从一个简单的开始。你可以代替
of(files_raw)
.pipe(
flatMap((file) => file),
使用(原始文件)中的
现在让我们进入要点的核心。您希望通过this.ms.fetchUploadURL()
函数获取要使用的url(顺便说一句,这类函数没有任何参数,这让我感到惊讶,这表明它总是返回相同的值,但这与此处无关)。然后调用this.ms.uploadDirectToS3
,将url和文件作为参数传递。如果是这种情况,则应首先调用this.ms.fetchUploadURL()
,然后通过操作符switchMap
切换到this.ms.uploadDirectToS3
返回的其他可观察对象。这些操作应在concatMap
中执行,以便按顺序执行
最终的代码可能是这样的
from(files_raw)
.pipe(
tap((file) => console.log("Firing 1", file)),
concatMap((file) => {
return fetchUploadURL().pipe(
tap((file) => console.log("Firing 2", file)),
switchMap(url => uploadDirectToS3(url, file))
);
}),
)
.subscribe(
d => console.log('subscribe', d),
err => console.error(err)
)
这里是对新代码的模拟我的答案来得有点晚,但我将为遇到类似问题的人发布它:
看起来像
this.ms.fetchUploadURL().pipe(withLatestFrom(of(file)))
从不完成,这会阻止concatMap消费(映射)后续项目
我不是JS开发人员,但在RxJava中,可以像这样重现您的问题:
Observable.just(1,2,3,4)
.doOnComplete { Log.d("TAG", "Complete 1") }
.doOnNext { Log.d("TAG", "before concatMap $it") }
.concatMap { someObservable(it) }
.doOnComplete { Log.d("TAG", "Complete 2") }
.doOnNext { Log.d("TAG", "after concatMap $it") }
.subscribe()
其中someObservable
实现如下所示:
fun observable(int: Int): Observable<Int> {
return Observable.create {
it.onNext(int)
}
}
before concatMap 1
after concatMap 1
before concatMap 2
after concatMap 2
before concatMap 3
after concatMap 3
before concatMap 4
after concatMap 4
Complete 1
Complete 2
Concat映射(另一个可观察对象)永远不会完成,因为映射器可观察对象永远不会完成
只需在someObservable
中添加onComplete()
即可解决此问题。
输出如下所示:
fun observable(int: Int): Observable<Int> {
return Observable.create {
it.onNext(int)
}
}
before concatMap 1
after concatMap 1
before concatMap 2
after concatMap 2
before concatMap 3
after concatMap 3
before concatMap 4
after concatMap 4
Complete 1
Complete 2
我认为RxJS中的情况大致相同。
请检查mapper的实施情况。谢谢您的详细回复。您的答案是100%有意义的…在concatMap中包装两个http请求是有意义的,但是…它仍然不起作用。没有返回错误,第一个文件始终成功上载到AWS S3,但第二个文件从未启动。在第一个“订阅”注销后,它仍然挂起。您可能需要检查网络日志,查看是否触发了第二个请求。您可能还想看看uploadDirectToS3
方法中发生了什么。