在同步函数中正确执行异步函数
Execute correctly async functions at sync functions
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 异步执行 subTasks
最后,我尝试抓住 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
变量,因此它是隐含的全局变量 - 它没有块作用域。它在每个 maintask 的每次迭代 and 中被重新分配。所以,异步后await
里面的for
:
for (subTask of subTasks) {
await subTaskHandler(defaultTimeout)
console.log(`${mainTask} -> ${subTask}: Completed`)
}
在任何 await
解析时,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()
您还可以考虑使用严格模式 and/or 一个 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()
Error: Unhandled promise rejection: ReferenceError: subTask is not defined
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 异步执行 subTasks 最后,我尝试抓住 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
变量,因此它是隐含的全局变量 - 它没有块作用域。它在每个 maintask 的每次迭代 and 中被重新分配。所以,异步后await
里面的for
:
for (subTask of subTasks) {
await subTaskHandler(defaultTimeout)
console.log(`${mainTask} -> ${subTask}: Completed`)
}
在任何 await
解析时,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()
您还可以考虑使用严格模式 and/or 一个 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()
Error: Unhandled promise rejection: ReferenceError: subTask is not defined