我当前正在发出一个返回某些文件和用户数据的请求。
对于每个文件,我想返回一个包含数据的对象,但其中一个键依赖于另一个请求。
如何发出此请求,以便 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
)。
关于javascript - 如何在嵌套对象数组中获取 RxJs Observable 的值来解析?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69937057/