这是一个比较理论性的问题。我原本想把这个问题叫做 能否对地图进行两次迭代?但听起来,这听起来像一个反模式。所以我想我只是方法不对。
另外注意:这里的数据作为一个抽象的服务器。我知道我在这里用这里提供的数据所做的事情是不必要的,但 请不要太过执着于数据结构。 和什么的。它并不能代表我正在处理的真实的(更复杂的,进一步说是由客户提供的,我不能改变的)数据。相反,我们可以把问题看作是 如何为每个数组项目返回结构化的异步调用。 拜托 :-)
我的问题归结起来是这样的。
id
上,我需要执行两个独立的异步调用。id
实例)所以作为一个例子,想象一下我有这两个数据集。
const dataMessages = [
{ id: "a", value: "hello" },
{ id: "b", value: "world" }
];
const dataNames = [
{ id: "a", name: "Samuel" },
{ id: "b", name: "John" },
{ id: "c", name: "Gustav"},
];
和一个API调用模拟。
const fetchFor = async (collection: Object[], id: string): Promise<Object> => {
const user = collection.find(user => user.id === id);
if (!user) {
throw Error(`User ${id} not found`);
}
return user;
};
现在 我要打电话给... fetchFor()
函数,用于两个数据集,大概是在内部的内部。Promise.all
,给定 forEach
并不是异步的,从预定的数组的 id
s.
我在想类似于 map
承诺清单 Promise.all
来执行。当你只需要映射一个api-call的时候,这很好用。
const run = async () => {
const result = await Promise.all(
['a', 'b'].map(id => fetchFor(dataMessages, id)
)
console.log(result) // [{id: 'a', value: 'hello'}, {id: 'b', value: 'world}]
}
但是我需要同时返回两个承诺的代码
fetchFor(dataMessages, id)
fetchFor(dataNames, id)
里面 Promise.all
承诺数组。
我想我总是可以简单地做一个
flatMap
的两个映射的两个实例的API调用,但这听起来有点愚蠢,因为考虑到
- 我会在同一个数组上做两次array.map。
- 我的数据结构在逻辑上没有连接 (同一用户的两个独立的数组项目,甚至不会跟在对方后面)
所以,理想情况下,我希望返回数据的形式为
const result = await Promise.all([...])
console.log(result)
/* [
* {id: 'a', message: 'hello', name: 'Samuel'},
* {id: 'b', message: 'world', name: 'John'},
* ]
还是说,我只需要做承诺的平面图,然后在解决的Promise.all上的一个单独的处理程序中,根据id标识符做数据合并到对象上?
我在这里提供了一个单api-call模拟的工作示例,所以你不必复制粘贴。
对于这样的问题,正确的常用方法是什么?
你可以嵌套 Promise.all
的调用。
const [messages, names] = await Promise.all([
Promise.all(
['a', 'b'].map(id => fetchFor(dataMessages, id)
),
Promise.all(
['a', 'b', 'c'].map(id => fetchFor(dataNames, id)
)
]);
如果你想在检索后将结果合并,这只是一个标准的数据操作问题。