2017-12-04 13 views
1

자바 스크립트에서 콜백 지옥을 극복하기 위해 SQLServer 프로 시저로 작성된 레거시 코드에서 비동기를 사용하려고합니다. 하지만 코드가 올바르게 작성되지 않을지 잘 모르겠습니다.비동기를 사용하여 노드 js에서 올바르게 대기합니다

첫 번째 혼란스러운 점은 async 함수가 반환 될 때, 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); 
    } 
}; 

답변

1

당신은 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를 직접 처리해야합니다. try/catch는이 비동기 작업의 결과를 처리 할 수 ​​없습니다.

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); 
    }); 

}; 

이 난 강력하게 그것의 묘리를 터득하기 위해 몇 가지 약속 관련 기사를 읽는 것이 좋습니다. 그들은 매우 편리하고 강력하지만 다른 JS 패턴 (async 콜백, try/catch ...)과 혼합 될 때 약간의 고통을 가져옵니다.