[英]Iterate over the entries of a Map with an asynchronous callback function
I want to iterate the entries of a Map with an asynchronous callback function. The callback function should be started immediately for all elements.我想用异步回调 function 迭代Map的条目。应该立即为所有元素启动回调 function。
I ended up with the following code, which works but looks too complicated:我最终得到了以下代码,它可以工作但看起来太复杂了:
async function test() {
const map1 = new Map();
map1.set('a', 1);
map1.set('b', 2);
map1.set('c', 3);
await Promise.all(Array.from(map1.entries()).map(async([
key,
value
]) => {
await doSomeThing(key, value);
await doSomeOtherThing(key, value);
}
}
Is there an easier way to achieve this?有没有更简单的方法来实现这一目标?
According to MDN , Promise.all() takes an iterable of promises and waits for them to resolve. 根据 MDN , Promise.all() 接受一个可迭代的承诺并等待它们解决。 An iterable may be an array, as in your code, or a dedicated generator created by a generator function.
一个可迭代对象可能是一个数组,就像在您的代码中一样,或者是由生成器 function 创建的专用生成器。 I don't know if this meets your definition of "easier", but here's one way to do it:
我不知道这是否符合您对“更容易”的定义,但这是一种方法:
function* processMap(map, callback) {
for (const entry of map.entries())
yield callback(entry);
}
async function test() {
const map = new Map();
map.set("a", 1);
map.set("b", 2);
map.set("c", 3);
const processEntry = async (entry) => {
await doSomeThing(entry);
await doSomeOtherThing(entry);
};
await Promise.all(processMap(map, processEntry));
}
You could do something shorter你可以做一些更短的事情
Array.from(map1.entries())
could be rewritten to [...map1]
Array.from(map1.entries())
可以重写为[...map1]
doSomeOtherThing
does not depend on doSomeThing
so we could call them two concurrentlydoSomeOtherThing
不依赖于doSomeThing
所以我们可以同时称它们为两个await Promise.all(
[...map1].flatMap(([key, val]) => [
doSomeThing(key, val),
doSomeOtherThing(key, val),
])
)
const doSomeThing = (key, val) => new Promise(res => { console.log("doSomeThing start", key, val) setTimeout(() => { console.log("doSomeThing finish", key, val) res() }, 1000) }) const doSomeOtherThing = (key, val) => new Promise(res => { console.log("doSomeOtherThing start", key, val) setTimeout(() => { console.log("doSomeOtherThing finish", key, val) res() }, 2000) }) async function test() { const map1 = new Map() map1.set("a", 1) map1.set("b", 2) map1.set("c", 3) /* await Promise.all( Array.from(map1.entries()).map(async ([key, value]) => { await doSomeThing(key, value) await doSomeOtherThing(key, value) }) ) */ await Promise.all( [...map1].flatMap(([key, val]) => [ doSomeThing(key, val), doSomeOtherThing(key, val), ]) ) } test().then(() => { console.log("done") })
All the bloat comes from the fact that there is no built in equivalent to Array.map()
to map over Iterables.所有的臃肿都来自这样一个事实,即没有内置等效于
Array.map()
到 map over Iterables。
But you can write a little utility to do the job.但是您可以编写一个小实用程序来完成这项工作。
function* map(iterable, mapper) {
for (const item of iterable)
yield mapper(item)
}
async function test() {
const map1 = new Map();
map1.set('a', 1);
map1.set('b', 2);
map1.set('c', 3);
await Promise.all(map(
map1,
async ([key, value]) => {
await doSomeThing(key, value);
await doSomeOtherThing(key, value);
}
));
}
Personally, I would prefer to break the code using the simpler and readable for...of
syntax with a few descriptive variables.就个人而言,我更喜欢使用更简单且可读
for...of
语法和一些描述性变量来破坏代码。 In such cases, "easier" is all about making the code less error-prone, easier to read and understand and above all, maintain in the long run.在这种情况下,“更容易”就是使代码更不容易出错,更容易阅读和理解,最重要的是,从长远来看,维护。
(async function(){
const map1 = new Map();
map1.set('a', 1);
map1.set('b', 2);
map1.set('c', 3);
const asyncOperations = [];
for (const [key, value] of map1) {
asyncOperations.push(async ()=>{
await DoSomeThing(key, value);
await DoSomeOtherThing(key, value);
});
}
await Promise.all( asyncOperations );
}());
The solution below uses iter-ops library:下面的解决方案使用iter-ops库:
import {pipe, toAsync, map, wait} from 'iter-ops';
const i = pipe(toAsync(map1), map(async ([key, value]) => {
await doSomeThing(key, value);
await doSomeOtherThing(key, value);
return [key, value]; // or something else (result)
}), wait());
// trigger processing + print result:
for await(let res of i) {
console.log(res);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.