在节点js中正确使用asynchronous

为了克服JavaScript中的callback地狱,我试图使用从SQLServer过程中编写的遗留代码asynchronous等待。 但是我不确定我的代码是否可以正确写入。

我的第一个令人困惑的地方是,asynchronous函数返回时,是否应该返回resolve()作为布尔值,或只是返回拒绝和try-catch处理?

这是我的代码片段。 请纠正我正确的方向。

apiRoutes.js

app.route('/api/dansok/cancelDansok') .post(dansokCancelHandler.cancelDansok); 

dansokCancelController.js

 const sequelize = models.Sequelize; const jwt = require('jsonwebtoken'); async function jwtAccessAuthCheck(accessToken) { if (!accessToken) { return Promise.reject('Empty access token'); } jwt.verify(accessToken,"dipa",function(err){ if(err) { return Promise.reject('TokenExpiredError.'); } else { return Promise.resolve(); } }); } async function checkFeeHist(dansokSeqNo) { let feeHist = await models.FeeHist.findOne({ where: { DansokSeqNo: dansokSeqNo} }); return !!feeHist; } async function getNextDansokHistSerialNo(dansokSeqNo) { .... } async function getDansokFee(dansokSeqNo) { .... } async function doCancel(dansokSeqNo) { try { if (await !checkFeeHist(dansokSeqNo)) { log.error("doCancel() invalid dansokSeqNo for cancel, ", dansokSeqNo); return; } let nextDansokSerialNo = await getNextDansokHistSerialNo(dansokSeqNo); await insertNewDansokHist(dansokSeqNo, nextDansokSerialNo); await updateDansokHist(dansokSeqNo); await updateVBankList(dansokSeqNo, danokFee.VBankSeqNo); await getVBankList(dansokSeqNo); } catch (e) { log.error("doCancel() exception:", e); } } exports.cancelDansok = function (req, res) { res.setHeader("Content-Type", "application/json; charset=utf-8"); const dansokSeqNo = req.body.DANSOKSEQNO; const discKindCode = req.body.HISTKIND; const worker = req.body.PROCWORKER; const workerIp = req.body.CREATEIP; const accessToken = req.headers.accesstoken; //check input parameter if (!dansokSeqNo || !discKindCode || !worker || !workerIp) { let e = {status:400, message:'params are empty.'}; return res.status(e.status).json(e); } try { jwtAccessAuthCheck(accessToken) .then(() => { log.info("jwt success"); doCancel(dansokSeqNo).then(() => { log.info("cancelDansok() finish"); res.status(200).json({ message: 'cancelDansok success.' }); }); }); } catch(e) { return res.status(e.status).json(e); } }; 

您需要重写jwtAccessAuthCheck(accessToken),以便跟踪嵌套任务的结果。 在你写的代码中:

 // Code that needs fixes! async function jwtAccessAuthCheck(accessToken) { // This part is fine. We are in the main async flow. if (!accessToken) { return Promise.reject('Empty access token'); } // This needs to be rewritten, as the async function itself doesn't know anything about // the outcome of `jwt.verify`... jwt.verify(accessToken,"dipa",function(err){ if(err) { // This is wrapped in a `function(err)` callback, so the return value is irrelevant // to the async function itself return Promise.reject('TokenExpiredError.'); } else { // Same problem here. return Promise.resolve(); } }); // Since the main async scope didn't handle anything related to `jwt.verify`, the content // below will print even before `jwt.verify()` completes! And the async call will be // considered complete right away. console.log('Completed before jwt.verify() outcome'); } 

更好的重写将是:

 // Fixed code. The outcome of `jwt.verify` is explicitly delegated back to a new Promise's // `resolve` and `reject` handlers, Promise which we await for. async function jwtAccessAuthCheck(accessToken) { await new Promise((resolve, reject) => { if (!accessToken) { reject('Empty access token'); return; } jwt.verify(accessToken,"dipa",function(err){ if(err) { reject('TokenExpiredError.'); } else { resolve(); } }); }); // We won't consider this async call done until the Promise above completes. console.log('Completed'); } 

一个替代签名,也可以在这个特定的用例中工作:

 // Also works this way without the `async` type: function jwtAccessAuthCheck(accessToken) { return new Promise((resolve, reject) => { ... }); } 

关于你的cancelDansok(req, res)中间件,由于jwtAccessAuthCheck保证返回一个Promise (你使它成为一个asynchronous函数),你还需要直接处理它返回的Promise。 try / catch不能处理这个asynchronous任务的结果。

 exports.cancelDansok = function (req, res) { ... jwtAccessAuthCheck(accessToken) .then(() => { log.info("jwt success"); return doCancel(dansokSeqNo); }) .then(() => { log.info("cancelDansok() finish"); res.status(200).json({ message: 'cancelDansok success.' }); }) .catch(e => { res.status(e.status).json(e); }); }; 

我强烈build议阅读一些Promise相关的文章,以获得它的挂钩。 它们非常方便和强大,但是当与其他JS模式(asynchronouscallback,try / catch …)混合时也会带来一点痛苦。