如何使用两个地图功能和两个获取 url
Posted
技术标签:
【中文标题】如何使用两个地图功能和两个获取 url【英文标题】:How to use two map function with two fetching url 【发布时间】:2021-11-23 10:37:13 【问题描述】:我有两个 api 我应该把它们变成这样的数组
[
key: "0",
label: 'Installation',
children: [
key: "0-0", label: 'Getting Started', url: 'https://reactjs.org/docs/getting-started.html' ,
key: "0-1", label: 'Add React', url: 'https://reactjs.org/docs/add-react-to-a-website.html' ,
key: "0-2", label: 'Create an App', url: 'https://reactjs.org/docs/create-a-new-react-app.html' ,
key: "0-3", label: 'CDN Links', url: 'https://reactjs.org/docs/cdn-links.html'
]
,
key: "1",
label: 'Main Concepts',
children: [
key: "1-0", label: 'Hello World', url: 'https://reactjs.org/docs/hello-world.html' ,
key: "1-1", label: 'Introducing JSX', url: 'https://reactjs.org/docs/introducing-jsx.html' ,
key: "1-2", label: 'Rendering Elements', url: 'https://reactjs.org/docs/rendering-elements.html' ,
key: "1-3", label: 'Components and Props', url: 'https://reactjs.org/docs/components-and-props.html' ,
key: "1-4", label: 'State and LifeCycle', url: 'https://reactjs.org/docs/state-and-lifecycle.html' ,
key: "1-5", label: 'Handling Events', url: 'https://reactjs.org/docs/handling-events.html'
]
];
顺便说一句,我有两个API,其中一个获取所有类别,第二个API是获取孩子的名字。所以我创建了链式提取,但我无法正确获取子对象。 children 数组变成了“children: Promise : Array(11)” 这里的满是什么意思?因为我的代码由于这个原因而无法工作。 我也想分享我的代码
getCategories()
return fetch('https://challenge.fnaghshin.com/api/cat')
.then((res) => res.json())
.then((d) =>
return Promise.all(
d.map((e) =>
return
key: e.id,
label: e.name,
date: e.created_at,
children: fetch(
`https://challenge.fnaghshin.com/api/catpro/$e.id`
)
.then((res) => res.json())
.then((d) =>
d.map((e) =>
return
key: e.id,
label: e.name,
;
)
),
;
)
);
);
我还使用 Promise.all() 来等待所有承诺都完成,而不是向右转数组。但我失败了
【问题讨论】:
你是否在 Promise.all() 中返回一个承诺? @Invizi 不,我该怎么做?fetch()
是一个异步函数。 async
函数返回承诺。 Promise.all()
不是递归的,所以不能解决那些深层嵌套的承诺。
@Ouroborus 你能帮我解决这个深深嵌套的承诺吗?
@sayinmehmet47 你可以运行我的答案,看看它是否符合你的要求。
【参考方案1】:
IMO 最干净的解决方案是使用 async/await,使用嵌套的 Promises 很快就会变得相当不可读。
async function getCategories()
const response = await fetch("https://challenge.fnaghshin.com/api/cat");
const categories = await response.json();
const childrenResponses = await Promise.all(
categories.map((cat) =>
fetch(`https://challenge.fnaghshin.com/api/catpro/$cat.id`)
)
);
const childrenData = await Promise.all(
childrenResponses.map((response) => response.json())
);
return categories.map((cat, index) => (
key: cat.id,
label: cat.name,
date: cat.created_at,
children: childrenData[index].map((child) => (
key: child.id,
label: child.title
))
));
所以首先你得到你的类别,这很简单。然后,您要做的是在 fetch 调用列表中使用 Promise.all()
,并使用您从类别 (childrenResponses
) 中获得的 ID。然后你必须做同样的事情,因为.json()
in fetch(它会更干净,例如axios
或类似的更高级别的库而不是fetch
),一旦你有了类别和childrenData,你只需要映射它你想要的方式。您可以通过执行例如使其更简洁一些。改为:
const categories = await fetch(
"https://challenge.fnaghshin.com/api/cat"
).then((res) => res.json());
虽然在我看来它的可读性较差。您可能还应该进行一些错误处理,例如使用 try/catch。
【讨论】:
这种用法也会报429错误。看看 ProductService.js:30 GET challenge.fnaghshin.com/api/catpro/8 429(请求太多) 这 99% 与你如何调用这个函数有关。它在隔离时工作得非常好(你甚至可以在 DevTools 控制台或其他东西中运行它)。此外,如果您到目前为止一直在通过调用向 API 发送垃圾邮件,那么您可能只是暂时被 API 阻止。等待几分钟/几小时,然后重试。【参考方案2】:Promise.all()
需要一个承诺数组,但您返回的是一个对象数组。承诺嵌套在对象的 children
属性中。所以我们需要做的是映射这些对象并返回嵌套的 prop children
并将其提供给 Promise.all()
我在第二个then
块中添加了一个异步函数,因此我可以将await
与Promise.all()
一起使用。这会导致代码的执行要等到所有承诺,即所有children
都已解决。之后我可以简单地返回结果。
function getCategories()
return fetch('https://challenge.fnaghshin.com/api/cat')
.then((res) => res.json())
.then(async (d) =>
const withChildren = d.map((e) =>
return
key: e.id,
label: e.name,
date: e.created_at,
children: fetch(`https://challenge.fnaghshin.com/api/catpro/$e.id`).then(res => res.json())
)
await Promise.all(withChildren.map(item => item.children))
return withChildren
)
429 (Too Many Requests)
似乎是一个速率限制,当您在特定时间内过于频繁地触发请求时。我也有。现在又没了。
PS:在这种情况下,不要在 map()
中使用 await,因为这会延长执行时间。因为在地图的每一次迭代中,它都会await
响应fetch()
,然后再进行下一次迭代并触发下一次fetch()
。因此,不是一次全部解雇(基本上),而是一个接一个地解雇他们。一次将它们全部触发,然后等待 Promise.all()
会更快。
【讨论】:
【参考方案3】:这是一个基于承诺的版本。我将主要功能分成几部分,这样更容易阅读。
请注意,由于您向 API 发出了许多请求,您可能会收到 429: too many requests
警告。
要解决这个问题,您可以为每个请求使用代理,也可以检查状态代码并等待响应告诉您等待的时间。
const URL = 'https://challenge.fnaghshin.com/api/cat';
const CHILDREN_URL = `https://challenge.fnaghshin.com/api/catpro/`;
function getCategories()
return fetch(URL)
.then(res => res.json())
.then(data => Promise.all(data.map(getSubCategories)));
function getSubCategories(data)
return fetch(CHILDREN_URL + data.id)
.then(res => res.json())
.then(info => (
key: data.id,
label: data.name,
date: data.created_at,
children: info.map(e => (
key: e.id,
label: e.title,
)),
));
getCategories()
.then(console.log)
.catch(console.log)
【讨论】:
以上是关于如何使用两个地图功能和两个获取 url的主要内容,如果未能解决你的问题,请参考以下文章
如何使用LatLng在谷歌地图v2中以公里为单位获取两个地方之间的距离