Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/438.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript concatMap无法处理数组中的所有项_Javascript_Rxjs - Fatal编程技术网

Javascript concatMap无法处理数组中的所有项

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)),

我正在处理一系列文件。对于每个文件,我需要请求正确的上载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((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
方法中发生了什么。