如何等待异步函数执行完成后再执行后续语句
问题根因
你的await等待逻辑失效,Kendo Window提前弹出,是代码存在三个明确问题导致的:
- 逻辑写在
.done()回调中:jQuery的ajax.done()只有请求成功才会触发,请求失败时这个回调完全不执行,里面的UI解锁、判断、resolve逻辑全不会跑 - Promise缺少分支resolve:请求失败的分支没有任何
resolve()调用,Promise会永远处于pending挂起状态,await拿不到返回值 - 变量未声明:
isSuccess没有做局部作用域声明,属于隐式全局变量,多次快速触发请求时值会互相覆盖,判断逻辑完全不可靠
另外jQuery 1.5及以上版本的$.ajax本身就返回和Promise标准兼容的Deferred对象,可以直接被await,不需要手动套一层new Promise,写法更简洁也不容易出错。
可直接运行的修正代码
VerifyData本身的async/await写法没有问题,只需要重写additionalCheck即可:
function additionalCheck(Ids) { return $.ajax({ url: '@Url.Action("GetDetails", "Data")', type: 'POST', dataType: "text", data: { ids: Ids } }) .then(data => { $.unblockUI(); const count = Number(data); if (count > 0) { MessageBox("Operation Invalid."); return false; } return true; }) .catch(() => { $.unblockUI(); MessageBox("Error. Please try again."); return false; }); }
修正后逻辑:不管ajax请求成功、失败、还是返回count大于0的情况,都会正常返回布尔值给await,不会出现挂起。只有返回
true的时候才会执行打开Kendo Window的逻辑,完全符合预期。
手动包装Promise的正确写法(不推荐,仅作参考)
如果你不想直接用ajax返回的Deferred对象,手动写Promise时必须保证所有分支都能结束Promise,同时做好变量声明:
function additionalCheck(Ids) { let count = 0; let isSuccess = false; // 局部声明,避免全局污染 return new Promise(resolve => { $.ajax({ url: '@Url.Action("GetDetails", "Data")', type: 'POST', dataType: "text", data: { ids: Ids }, success: function (data) { isSuccess = true; count = Number(data); }, error: function () { isSuccess = false; } }).always(function () { // 用always代替done,保证成功失败都会执行后续逻辑 $.unblockUI(); if (isSuccess) { if (count > 0) { MessageBox("Operation Invalid."); resolve(false); } else { resolve(true); } } else { MessageBox("Error. Please try again."); resolve(false); // 错误分支必须resolve,否则Promise永远不会结束 } }); }); }
内容的提问来源于stack exchange,提问作者AJ31
相关产品推荐
相关产品推荐

