如何在要解析的嵌套对象数组中获取 RxJs Observable 的值?

How can I get value of RxJs Observable in a nested array of objects to resolve?

我目前正在请求 returns 某些文件和用户的数据。

对于每个文件,我想 return 一个包含数据的对象,但其中一个键依赖于另一个请求。

如何发出此请求,以便 getData 函数等待内部可观察值解析为一个值?

function getData() {
    return forkJoin([
             filesApiRequest),
             userApiRquest
           ])
        .pipe(map(([files, userInfo]) => {
          return files.getFilesList()
              .map((file) => {
                const name = file.getName();
                const importantInfo = importantInfoCall(userInfo.name, name); // returns an observable. 
                // How can I get the value from this before returning? I need this piece of data for each 
                // file in the files list. 

                return {
                  data1,
                  data2,
                  name,
                  ...,
                  hasImportantInfo: importantInfo
                };
              })
        }));
  }

您需要使用“高阶映射运算符”(switchMap),它将订阅您的内部可观察源并发出您需要的数据。在您的情况下,您需要进行多次调用(每个文件一个调用),因此您可以将文件列表映射到发出所需数据的可观察对象数组。您可以再次使用 forkJoin 将所有这些调用包装到一个单独的可观察对象中:

function getData() {
    return forkJoin([filesApiRequest, userApiRquest]).pipe(
        switchMap(([files, userInfo]) => forkJoin(
            // return array of observables
            files.getFilesList().map(f => toDataWithImportantInfo$(f, userInfo))
        ))
    );
}
function toDataWithImportantInfo$(file, userInfo) {
    const name = file.getname();

    return importantInfoCall(userInfo.name, name).pipe(
        map(importantInfo => ({
            data1,
            data2,
            name,
            ...,
            hasImportantInfo: importantInfo
        })
    );
}

当您有大量请求时,

forkJoin 不是最佳解决方案,因为它会同时执行所有请求(也许您不想开始一次 500 个 http 请求).

为了限制请求的数量,我们可以使用merge代替,因为它提供了一个并发参数:

function getData() {
    return forkJoin([filesApiRequest, userApiRquest]).pipe(
        switchMap(([files, userInfo]) => merge(
            files.getFilesList().map(f => toDataWithImportantInfo$(f, userInfo))
        , 5)), // MAX 5 CONCURRENT
        toArray()
    );
}

forkJoin 在所有源完成时发出所有结果的数组。 merge 单独发出每个结果,因此如果您想在所有内部源完成后发出单个数组(而不是单独发出),则需要 toArray