什么库或模式将这么多 cb 的样板减少到 1 cb?
What library or pattern reduces boilerplate for this many cb to 1 cb?
我发现自己在我的代码中写了很多这样的东西,而且我确信那里有一个标准库可以使这变得更简单——希望是一个单一的班轮。本质上,我想为数组编写一个异步处理程序,它对数组中的每个项目执行一些异步工作,并回调关于数组上的所有工作:(A) 在数组中的每个项目都被成功异步处理后,或者(B) 如果有任何错误,如果可能的话尽早退出——但只是这样主回调被精确调用一次。
希望得到适用于浏览器和节点的答案:
// @items - an array
// @cb - callback after all of `items` processed, taking an optional Error first argument
function doForEachAndCb(items, cb) {
var exitEarly, tasksRemaining;
if (!items || typeof items !== 'object' || !items.length) {
cb();
return;
}
tasksRemaining = items.length;
exitEarly = false;
function finishOneTask(err) {
// finishOneTask() is no-op if previously called with an error passed.
if (exitEarly) {
return;
}
if (!!err) {
exitEarly = true;
cb(err);
return;
}
tasksRemaining--;
if (tasksRemaining === 0) {
cb();
}
}
items.map( (v) => {
try {
handleItemAsync(items[v], finishOneTask);
} catch (err2) {
finishOneTask(err2);
}
});
}
查看 async#map()
:
async.map(items, (item, callback) => {
// do something async
...
// when async operation has finished, call
// the callback with the mapped value
callback(null, value);
}, (err, mappedItems) => {
...
});
如果不需要构建映射值数组,可以使用 async#each
。
async#map()
和 async#each()
也有顺序版本,其中每个项目仅在前一个处理步骤完成后才处理("regular" 版本并行处理所有项目) : async#mapSeries()
和 async#eachSeries()
.
我发现自己在我的代码中写了很多这样的东西,而且我确信那里有一个标准库可以使这变得更简单——希望是一个单一的班轮。本质上,我想为数组编写一个异步处理程序,它对数组中的每个项目执行一些异步工作,并回调关于数组上的所有工作:(A) 在数组中的每个项目都被成功异步处理后,或者(B) 如果有任何错误,如果可能的话尽早退出——但只是这样主回调被精确调用一次。
希望得到适用于浏览器和节点的答案:
// @items - an array
// @cb - callback after all of `items` processed, taking an optional Error first argument
function doForEachAndCb(items, cb) {
var exitEarly, tasksRemaining;
if (!items || typeof items !== 'object' || !items.length) {
cb();
return;
}
tasksRemaining = items.length;
exitEarly = false;
function finishOneTask(err) {
// finishOneTask() is no-op if previously called with an error passed.
if (exitEarly) {
return;
}
if (!!err) {
exitEarly = true;
cb(err);
return;
}
tasksRemaining--;
if (tasksRemaining === 0) {
cb();
}
}
items.map( (v) => {
try {
handleItemAsync(items[v], finishOneTask);
} catch (err2) {
finishOneTask(err2);
}
});
}
查看 async#map()
:
async.map(items, (item, callback) => {
// do something async
...
// when async operation has finished, call
// the callback with the mapped value
callback(null, value);
}, (err, mappedItems) => {
...
});
如果不需要构建映射值数组,可以使用 async#each
。
async#map()
和 async#each()
也有顺序版本,其中每个项目仅在前一个处理步骤完成后才处理("regular" 版本并行处理所有项目) : async#mapSeries()
和 async#eachSeries()
.