После создания обещанной версии func_a()
и func_b()
вы можете использовать Promise.all()
и await
агрегированные результаты в async function
без использования счетчика:
const promisify = fn => function () {
return new Promise((resolve, reject) => {
// forward context and arguments of call
fn.call(this, ...arguments, (error, result) => {
if (error) {
reject(error)
} else {
resolve(result)
}
})
})
}
const func_a_promisified = promisify(func_a)
const func_b_promisified = promisify(func_b)
async function loop_a_b (num1, num2) {
// await pauses execution until all asynchronous callbacks have been invoked
const results_a = await Promise.all(
Array.from(Array(num1).keys()).map(i => func_a_promisified(i))
)
const results_b = await Promise.all(
Array.from(Array(num2).keys()).map(j => func_b_promisified(j))
)
return {
a: results_a,
b: results_b
}
}
// usage
loop_a_b(3, 4).then(({ a, b }) => {
// iff no errors encountered
// a contains 3 results in order of i [0..2]
// b contains 4 results in order of j [0..3]
}).catch(error => {
// error is first encountered error in chronological order of callback results
})
Чтобы упростить беспорядок Array.from(...).map(...)
, вы можете написать вспомогательную генераторную функцию для одновременного вызова асинхронных функций:
function * loop_fn_n (fn, n) {
for (let i = 0; i < n; i++) {
yield fn(n)
}
}
Затем измените loop_a_b
на:
async function loop_a_b (num1, num2) {
// await pauses execution until all asynchronous callbacks have been invoked
const results_a = await Promise.all(
loop_fn_n(func_a_promisified, num1)
)
const results_b = await Promise.all(
loop_fn_n(func_b_promisified, num2)
)
return {
a: results_a,
b: results_b
}
}
Как указывает @ OleksiiTrekhleb , реализованная здесь функция promisify
также доступна вОсновной модуль Node.js util
.