JavaScript Async/Await 不生效:如何实现代码按1-2-3-4顺序执行
核心代码错误与修正方案
目前代码存在的3个硬错误
- 死代码导致日志4不执行:JS函数执行到
return语句后会立刻终止运行,后续写的所有代码都属于永远不会触发的无效代码,你把console.log("ending function")写在了return后面,自然永远看不到输出。 - 异步对象取错值:
setBoltEnum是普通函数,内部既没有return值,也没有创建带array属性的对象;你用new setBoltEnum()拿到的是一个完全空的实例,它上面根本不存在array属性,所以await result.array拿到的永远是undefined,完全绕过了AJAX的异步返回流程。 - 执行顺序错配:因为没有正确await AJAX返回的Promise,你在调用setBoltEnum后立刻同步执行标3的日志,不等AJAX响应回来就先把
undefined打了出来,等AJAX异步回调跑完才会执行标2的日志,最终顺序完全混乱。
修正后的可运行代码
1. 重写AJAX处理函数setBoltEnum
去掉不必要的全局变量赋值,直接返回jQuery的AJAX Promise对象:
function setBoltEnum(Thread_Code){ console.log(Date.now() + " - 1 - calling AJAX"); // 直接return $.ajax返回的Promise,不要赋值给全局变量 return $.ajax({ url: 'EnumHelper.php', type: 'POST', dataType: "html", data: { value: Thread_Code, col_out: 'Descr', col_search: 'Thread_Code', tablename: 'Bolt_List' }, success: function (response) { const parsedResult = JSON.parse(response); console.log(Date.now() + " - 2 - got AJAX response: " + parsedResult.resp); return parsedResult; }, error: function(XMLHttpRequest, textStatus, exception) { alert("Ajax failure\n" + errortext); }, async: true }); }
2. 调整枚举提供函数的执行逻辑
把return语句移到所有日志输出的最后,正确await AJAX返回的结果:
DatabaseGrid.prototype.initializeGrid = function(grid) { var self = this; grid.setEnumProvider('id_Bolt', new EnumProvider({ getOptionValuesForEdit: async function (grid, column, rowIndex) { var Thread_Code = grid.getValueAt(rowIndex, grid.getColumnIndex("Thread_Code")); // 直接await setBoltEnum返回的Promise,不要用new,不要取不存在的array属性 const enumResult = await setBoltEnum(Thread_Code); console.log(Date.now() + " - 3 - " + enumResult.Descr); console.log(Date.now() + " - 4 - " + "ending function"); // 所有逻辑跑完再return结果,这才不会产生死代码 return enumResult.Descr; } })); };
执行顺序说明
修正后流程完全符合预期:
- 触发单元格编辑调用async函数,同步进入setBoltEnum打印标1日志
- 触发异步AJAX请求,async函数因await关键字暂时挂起,不阻塞后续页面操作
- AJAX请求完成,进入成功回调打印标2日志,把解析后的响应作为Promise的返回值
- 回到挂起的async函数,拿到AJAX返回结果,依次打印标3、标4日志
- 最终把枚举选项值返回给editablegrid完成单元格渲染
注意:editablegrid文档提到的“AJAX需使用同步模式”是基于老旧的同步阻塞JS逻辑写的,如果你用现在的async函数作为回调,它返回的是Promise对象,需要确认editablegrid源码在调用
getOptionValuesForEdit时有没有做await处理——如果没有,哪怕你内部逻辑写的没问题,网格拿到的也会是Promise对象而不是实际的枚举值。不需要刻意把AJAX改成async:false的同步模式,这种写法现在浏览器会抛出控制台警告,还会直接卡死页面交互。
内容的提问来源于stack exchange,提问作者Jeffrey Morgan
相关产品推荐
相关产品推荐

