node.js - 在同步函数中正确执行异步函数
问题描述
const mainTasks = ['mainTask1', 'mainTask2', 'mainTask3', 'mainTask4']
const subTasks = ['subTask1', 'subTask2', 'subTask3']
const defaultTimeout = 1000
// SubTasks should be run as async
// Tasks should be run as sync
const subTaskHandler = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, defaultTimeout * 2);
})
}
const main = async () => {
await Promise.all(
mainTasks.map((mainTask, index) => {
return new Promise(resolve => {
setTimeout(async () => {
for (subTask of subTasks) {
await subTaskHandler(defaultTimeout)
console.log(`${mainTask} -> ${subTask}: Completed`)
}
resolve()
}, defaultTimeout + index * 1000)
})
})
)
console.log('done')
}
main()
我将mainTasks作为 sync 和subTasks作为 async 执行 最后,我尝试抓住mainTasks 以及subTasks都完成的点。看来我明白了但我遇到了意想不到的结果。
mainTask1 -> subTask1: Completed
mainTask2 -> subTask1: Completed
mainTask3 -> subTask2: Completed
mainTask1 -> subTask2: Completed
mainTask4 -> subTask3: Completed
mainTask2 -> subTask2: Completed
mainTask3 -> subTask3: Completed
mainTask1 -> subTask3: Completed
mainTask4 -> subTask3: Completed
mainTask2 -> subTask3: Completed
mainTask3 -> subTask3: Completed
mainTask4 -> subTask3: Completed
done
mainTask4 -> subTask1和 2在哪里?
解决方案
跟你的
for (subTask of subTasks) {
您忘记声明subTask
变量,因此它是隐式全局的 - 它没有块范围。它在每次迭代和每个主要任务上都会重新分配。所以,在异步await
之后for
:
for (subTask of subTasks) {
await subTaskHandler(defaultTimeout)
console.log(`${mainTask} -> ${subTask}: Completed`)
}
到任何await
s 解决时,该subTask
变量将保存在最近初始化的子任务期间分配给它的值(而不是在当前子任务期间分配给它的变量)。
改成:
for (const subTask of subTasks) {
它会按预期工作。
const mainTasks = ['mainTask1', 'mainTask2', 'mainTask3', 'mainTask4']
const subTasks = ['subTask1', 'subTask2', 'subTask3']
const defaultTimeout = 1000
// SubTasks should be run as async
// Tasks should be run as sync
const subTaskHandler = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, defaultTimeout * 2);
})
}
const main = async () => {
await Promise.all(
mainTasks.map((mainTask, index) => {
return new Promise(resolve => {
setTimeout(async () => {
for (const subTask of subTasks) {
await subTaskHandler(defaultTimeout)
console.log(`${mainTask} -> ${subTask}: Completed`)
}
resolve()
}, defaultTimeout + index * 1000)
})
})
)
console.log('done')
}
main()
您还可以考虑使用严格模式和/或 linter 来更早地捕获这些错误:
'use strict';
const mainTasks = ['mainTask1', 'mainTask2', 'mainTask3', 'mainTask4']
const subTasks = ['subTask1', 'subTask2', 'subTask3']
const defaultTimeout = 1000
// SubTasks should be run as async
// Tasks should be run as sync
const subTaskHandler = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, defaultTimeout * 2);
})
}
const main = async () => {
await Promise.all(
mainTasks.map((mainTask, index) => {
return new Promise(resolve => {
setTimeout(async () => {
for (subTask of subTasks) {
await subTaskHandler(defaultTimeout)
console.log(`${mainTask} -> ${subTask}: Completed`)
}
resolve()
}, defaultTimeout + index * 1000)
})
})
)
console.log('done')
}
main()
错误:未处理的承诺拒绝:ReferenceError:未定义子任务
推荐阅读
- haskell - 导入作为 Haskell 中的运算符的类型族
- bixby - 具有多列的输入视图
- logstash - TCP入口点的Nginx-Ingress不起作用
- c - 在 C 中使用 setenv()
- android - React Native + Expo 获取缓存控制
- kubernetes - 在 Kubernetes 下调度任务失败
- javascript - 网络抓取功能返回“未定义”,但在我使用 console.log 时有效
- python - 带有quandl的url NotFoundError
- mysql - mysql group by Select group 为一列的不同行选择值
- apache-spark - 找不到翻译