NodeJS异步循环顺序错乱、输出undefined如何解决
异步顺序执行代码异常问题
问题现象
尝试多种实现方式均无法正常生效:代码中msg1和msg2是需要按顺序调用(先执行前者再执行后者)的函数占位符,使用普通for循环实现时第二次循环会输出"unknown"。查阅资料尝试对应实现方案后,始终无法得到预期结果。
预期输出
msg1 msg2
实际输出
msg1 msg1
初始问题代码
var data = { "messages": ["msg1", "msg2"], "i": -1 } const increment = async () => { data.i = await data.i + 1; }; const test = async () => { data.messages.forEach((fcn) => { increment(data) .then(() => { console.log(data.messages[data.i]) return data }) }) }; test(data)
问题根因
forEach不会等待内部异步Promise执行完成,所有increment调用几乎同时触发,等.then回调执行时,全局索引data.i已经被并发修改,才会出现两次打印msg1的问题await data.i + 1属于无效写法,data.i是普通同步数值,不需要加await,多余的await反而会干扰异步执行顺序
基础修复方案
不要用forEach处理需要顺序执行的异步逻辑,改用for...of循环搭配await,保证上一步异步执行完成、索引更新后,再进入下一轮逻辑,同时去掉无意义的await:
var data = { "messages": ["msg1", "msg2"], "i": -1 } const increment = () => { data.i = data.i + 1; }; const test = async () => { for (const fcn of data.messages) { await increment(); console.log(data.messages[data.i]) // 此处替换为实际的fcn调用逻辑即可 } }; test(data)
更新问题:接入业务代码后多执行一次、输出undefined的解决方案
之前加的data.i !== undefined判断逻辑无效,原因是多出来的执行轮次里data.i本身是合法数值,只是数值超过了messages数组的最大索引范围,才会取到undefined。
两种解决方式选其一即可:
- 从根源避免依赖全局共享索引做循环遍历,直接用for循环自带的索引控制执行次数,完全不会出现多跑一次的问题:
const test = async () => { for (let idx = 0; idx < data.messages.length; idx++) { const currentMsg = data.messages[idx]; // 此处放置需要顺序执行的业务逻辑 console.log(currentMsg) } };
- 如果业务逻辑必须维护全局
data.i变量,就把判断条件改成校验索引是否在数组有效范围内,而非判断i是否为undefined:
// 数组有效索引范围为0 到 数组长度-1 if (data.i >= 0 && data.i < data.messages.length) { console.log(data.messages[data.i]) }
内容的提问来源于stack exchange,提问作者user3877654
相关产品推荐
相关产品推荐

