后端提供一个list列表的接口和列表项详情itemDetail的接口,但是list接口返回的数据不完整,需要继续调用itemDetail获取更完整的数据。所以需要前端并发所有itemDetail接口,来获取详细数据。
请求走浏览器,因为浏览器本身就有一个队列去控制请求,会限制请求的并发,谷歌一次只让并发同时发送6个请求。所以考虑直接使用promise.all的方式实现好了。
Promise.all() MDN:promise处理异步任务并发方式的一种。
- 当所有输入的 Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是一个空的可迭代对象),并返回一个包含所有兑现值的数组。
- 如果输入的任何 Promise 被拒绝,则返回的 Promise 将被拒绝,并带有第一个被拒绝的原因。
(1)请求list接口,并setData存起来
(2)监听data的变化,依次遍历data数据,请求itemDetail接口
(3)等待所有itemPromise执行完毕,就可以得到所有item的数据了
// 数据缓存,同步的方式,可以实时最新的值
const metricStoreMapRef = useRef();
const handleCallMetricList = async () => {
try {
const nodePromises = data?.nodes.map(async (node) => {
const id = `${node.project_name}-${node.module_name}`;
// 获取每一项的详细数据
const metricItem = await getMetricList(node, 'node' as MttkArchitectureSelectedNodeType);
// 缓存
metricStoreMapRef.current.metric = {
...metricStoreMapRef.current?.metric,
[id]: metricItem,
};
return {
...node,
has_error: false,
};
});
const edgePromises = data?.edges.map(async (edge) => {
const { id } = getEdgeId(data?.nodes, edge);
const metricItem = await getMetricList(edge, 'edge' as MttkArchitectureSelectedNodeType);
// 缓存
metricStoreMapRef.current.metric = {
...metricStoreMapRef.current?.metric,
[id]: metricItem,
};
return {
...edge,
has_error: false,
};
});
// 关键点,获取所有的node和edge的数据,使用Promise.all
const nodeList = nodePromises && (await Promise.all(nodePromises));
const edgeList = edgePromises && (await Promise.all(edgePromises));
setGraphData({ nodes: nodeList || [], edges: edgeList || [] });
} catch (err) {
console.error(err);
// 如果出错的话,就先展示没有has_error的数据
notification.error({ message: `Get metrics failed: ${err}` });
data && setGraphData(data);
} finally {
setApiLoading(false);
}
};
useUpdateEffect(() => {
handleCallMetricList();
// 当请求到图原始的数据后,需要再去请求每个node/edge的metric数据,进而获取has_error
// data表示列表数据
}, [data]);