Node.js调用Authorize.net异步接口后无法执行后续await代码如何解决
报错的核心原因是await关键字仅可在标记了async的函数内部使用,将带await的SQL逻辑放入普通回调函数中就会触发该语法错误,可通过以下两种方案解决:
方案1:直接给回调函数加async修饰(改动最小)
只需给ctrl.execute的回调函数加上async关键字,即可在回调内部正常使用await:
var ctrl = new ApiControllers.CreateTransactionController(createRequest.getJSON()); // 给回调函数加上async修饰 ctrl.execute(async function () { var apiResponse = ctrl.getResponse(); var response = new ApiContracts.CreateTransactionResponse(apiResponse); // 原有交易结果处理逻辑保持不变 if (response != null) { if (response.getMessages().getResultCode() == ApiContracts.MessageTypeEnum.OK) { if (response.getTransactionResponse().getMessages() != null) { AuthorizeResult.status = 1; } else { if (response.getTransactionResponse().getErrors() != null) { AuthorizeResult.status = 0; // 可补充给AuthorizeResult.errorcode赋值的逻辑 } } } else { if (response.getTransactionResponse() != null && response.getTransactionResponse().getErrors() != null) { AuthorizeResult.status = 0; // 可补充给AuthorizeResult.errorcode赋值的逻辑 } else { AuthorizeResult.status = 0; } } } else { AuthorizeResult.status = 0; } // 直接放入SQL逻辑即可正常执行 const sqlString = ` insert into AuthorizeBillings (memberid, datetime, authorizeid, messagecode, status, amount, billingtype, errorcode) values (@memberid, @datetime, @authorizeid, @messagecode, @status, @amount, @billingtype, @errorcode )` try { const pool = await utils.poolPromise const recordset = await pool.request() .input('memberid', utils.sql.Int, memberid) // 补充其余参数的input配置 .input('errorcode', utils.sql.NVarChar, AuthorizeResult.errorcode) .query(sqlString) } catch (err) { console.log(err) } });
方案2:封装成Promise使用await顺序调用(更易维护)
如果想避免回调嵌套,让流程更清晰,可以将Authorize.net的交易调用封装为Promise,之后即可按顺序用await调用:
// 封装交易逻辑为Promise,返回处理后的结果 function executeTransaction(createRequest) { return new Promise((resolve, reject) => { const ctrl = new ApiControllers.CreateTransactionController(createRequest.getJSON()); ctrl.execute(function () { try { const apiResponse = ctrl.getResponse(); const response = new ApiContracts.CreateTransactionResponse(apiResponse); const AuthorizeResult = { status: 0, errorcode: '' } // 原有结果处理逻辑 if (response != null) { if (response.getMessages().getResultCode() == ApiContracts.MessageTypeEnum.OK) { if (response.getTransactionResponse().getMessages() != null) { AuthorizeResult.status = 1; } else { if (response.getTransactionResponse().getErrors() != null) { AuthorizeResult.errorcode = response.getTransactionResponse().getErrors()[0].getErrorCode() } } } else { if (response.getTransactionResponse() != null && response.getTransactionResponse().getErrors() != null) { AuthorizeResult.errorcode = response.getTransactionResponse().getErrors()[0].getErrorCode() } } } resolve(AuthorizeResult) } catch (err) { reject(err) } }) }) }
之后在外层async函数中按顺序调用即可:
// 外层函数必须加async修饰 async function processPayment() { try { // 第一步:等待交易接口返回结果 const AuthorizeResult = await executeTransaction(createRequest) // 第二步:执行SQL插入 const sqlString = ` insert into AuthorizeBillings (memberid, datetime, authorizeid, messagecode, status, amount, billingtype, errorcode) values (@memberid, @datetime, @authorizeid, @messagecode, @status, @amount, @billingtype, @errorcode )` const pool = await utils.poolPromise const recordset = await pool.request() .input('memberid', utils.sql.Int, memberid) // 补充其余参数的input配置 .input('errorcode', utils.sql.NVarChar, AuthorizeResult.errorcode) .query(sqlString) } catch (err) { console.log('支付流程出错:', err) } }
两种方案都能实现先获取接口返回值、再执行SQL的需求,方案2的代码可读性和可维护性更高。
内容的提问来源于stack exchange,提问作者Danielle
相关产品推荐
相关产品推荐

