如何解决Javascript:混合串行和并行处理
我正在寻找针对我的问题的ES6解决方案(我想这可能很常见……):
我有一个远程提供程序列表,每个提供程序都在一个页面上发布项目列表,每个项目详细信息在其他页面上。 我需要每小时(例如)一次从所有提供商获取所有商品的详细信息。
我想并行获取所有提供者列表,并在每个列表解析后立即并行地从该列表获取所有项的详细信息(我将根据需要限制请求以避免{{1} }错误,但这是另一个故事。
这是我的临时解决方案的实现:
ECONNRESET
它至少涉及两个问题:
- 我两次使用
const providers = [ { name: 'A',urlList: 'https://jsonplaceholder.typicode.com/users/?_start=0&_limit=1',urlItem: 'https://jsonplaceholder.typicode.com/posts?userId=%id%&_start=0&_limit=2',},{ name: 'B',urlList: 'https://jsonplaceholder.typicode.com/users/?_start=2&_limit=2',{ name: 'C',urlList: 'https://jsonplaceholder.typicode.com/users/?_start=4&_limit=2',]; const getList = (provider) => fetch(provider.urlList).then(res => res.json()); const getItems = (provider,list) => Promise.all( list.map(item => { return fetch(provider.urlItem.replace("%id%",item.id)).then(res => res.json()).then(res => res.map(r => ({ provider: provider.name,name: item.name,...r }))); }) ); const providerFetch = async provider => { console.log(`providerFetch ${provider.name} start`); try { const list = await getList(provider); const items = await getItems(provider,list); return items; } catch (error) { console.error(`providerFetch ${provider.name} error: ${error}`); } finally { console.log(`providerFetch ${provider.name} done`); } } (async () => { console.log('start'); const data = await Promise.all( providers.map(async provider => { const providerData = providerFetch(provider); return providerData; }) ); //console.dir(data,{ depth: 3 }); console.log(data.flat(2)); console.log('end'); })();
,所以我得到一个3维数组,而我更喜欢一个简单的一维数组...有没有办法让Promise.all()
来实现承诺的结果,不推他们? - 最严重的问题:我正在获取所有提供者列表,并且只有当所有提供者都准备好时,我才开始获取项(与预期的一样)。取而代之的是,我想在获取列表后立即开始为每个列表获取项目。您能给我些提示如何更改代码以实现它吗?
更新: 也要感谢@Bergi的评论,我可以理解:
- 要点1:这可以通过在最终数据上使用
Promise.all()
(2是要展平的深度)来简单解决;该解决方案并不是那么时尚,但是看起来flat(2)
只能推送,而不能合并。我确实更改了代码示例以进行显示。 - 要点2:
promise.All()
连续工作只是我的一个假设,可能是由于providerFetch
在此测试代码中是如此之快...事实上,在getList
返回之前增加了一个延迟,我可以看到有些getList
在所有getItems
完成之前确实开始执行。
解决方法
Promise.all
本身没有concat功能,但是javascript数组具有concat功能。因此,请在随后确认结果:
const result = await Promise.all(/* your original code ... */);
let data = [];
result.forEach(x => data = data.concat(x));
// now data is as you expect
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。