【问题标题】:How to convert Observable<string>[] to Observable<string[]>如何将 Observable<string>[] 转换为 Observable<string[]>
【发布时间】:2021-11-28 00:08:24
【问题描述】:

我有一个包含对象数组的 Observable,我想使用第二个 observable 将它们转换为不同的对象。这是一个更大项目的一部分,因此为了简化我的问题,我将有一个具有数字数组的可观察对象,我想将它们转换为字符串。我从以下开始。

    const response$ = of({results: [1, 2, 3]});
    response$.pipe(
        map((response) => {
            return response.results.map((id) => {
                return id.toString();
            })
        })
    )
    .subscribe((response: string[]) => {
        console.log(response);
    })

订阅中的响应将是预期的字符串数组。现在我需要使用第二个 observable 将数字转换为字符串(再次只是为了让问题更简单)。所以我用return of(id.toString()) 替换了return id.toString() 来模拟对可观察对象的第二次调用。

    const response$ = of({results: [1, 2, 3]});
    response$.pipe(
        map((response) => {
            return response.results.map((id) => {
                return of(id.toString());
            })
        }),
    )
    .subscribe((response: Observable<string>[]) => {
        
    })

现在响应的签名是Observable&lt;string&gt;[],但我需要响应是string[],所以我开始阅读其他 RxJS 运算符,最终得到以下结果。

    const response$ = of({results: [1, 2, 3]});
    response$.pipe(
        concatMap((response) => {
            return response.results.map((id) => {
                return of(id.toString());
            })
        }),
        concatAll()
    )
    .subscribe((response: string) => {
        console.log('bar', response);
    })

我使用了concatMap()concatAll(),因为我需要依次调用第二个可观察对象。现在的问题是我的响应是一个字符串,我接到三个电话给订阅者“1”“2”“3”。我需要string[] 的回复。在我的示例中,有人可以解释如何获取 Observable&lt;string&gt;[] 并将其转换为 Observable&lt;string[]&gt; 吗?

【问题讨论】:

    标签: rxjs-observables


    【解决方案1】:

    我认为您正在寻找的是:

    const response$ = of({results: [1, 2, 3]});
    response$.pipe(
        switchMap((response) => {
            // map array to observables and execute all with forkJoin
            return forkJoin(...response.results.map((id) => {
                return of(id.toString());
            }))
        })
    )
    .subscribe((response: string) => {
        console.log('bar', response);
    })
    

    但是,这将并行执行。如果需要内部顺序执行,可以使用concatreduce

    const response$ = of({results: [1, 2, 3]});
    response$.pipe(
        switchMap((response) => {
            // map array to observables and execute all with concat and collect results with reduce
            return concat(...response.results.map((id) => {
                return of(id.toString());
            })).pipe(reduce((acc, v) => acc.concat([v]), []))
        })
    )
    .subscribe((response: string) => {
        console.log('bar', response);
    })
    

    唯一需要注意的是确保response.results 中有项目。可能需要进行长度检查,例如:

    if (!response.results.length)
      return of([])
    

    【讨论】:

    • 感谢您的快速响应!我确实看过 forkJoin() 但它会并行处理而不是顺序处理吗?此外,它的节目在 VSCode 中的 rxjs6 处已贬值,但并未表示已弃用 (rxjs.dev/api/index/function/forkJoin)。我认为 concat() 会按顺序运行,对吧?
    • forkJoin 未被弃用。但是是的,它是并行执行,我添加了您需要为顺序执行的操作。
    • 那真是太好了。你能解释一下 concat() 方法中三个点 (...) 的作用吗?我熟悉传播运算符,但我认为这是不同的。
    • 它只是将数组转换为函数的参数。老实说,我不确定它是否需要再存在了,因为 RXJ 已经改变了几次他们的界面,现在它更灵活了,但它曾经是需要的,我这样做是出于习惯。
    • 嗯,我试过没有三个点,它返回 Observable[].
    猜你喜欢
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 2019-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多