try catch
捕獲異步鏈中的方法ctx.runInBackground(scope)
捕獲跳出異步鏈的方法// 舊代碼 class HomeController extends Controller { async buy () { const request = {}; const config = await ctx.service.trade.buy(request); // 下單後須要進行一次覈對,且不阻塞當前請求 setImmediate(() => { // 這裏的異常沒法被捕獲到,由於setImmediate跳出異步鏈 ctx.service.trade.check(request).catch(err => ctx.logger.error(err)); }); } } // 新代碼 class HomeController extends Controller { async buy () { const request = {}; const config = await ctx.service.trade.buy(request); // 下單後須要進行一次覈對,且不阻塞當前請求 ctx.runInBackground(async () => { // 這裏面的異常都會通通被 Backgroud 捕獲掉,並打印錯誤日誌 await ctx.service.trade.check(request); }); } }
首先eggjs間件機制是一個洋蔥模型。
洋蔥模型解釋以下:json
// config.[env].js exports.middleware = ['gqlErrorHandler','graphql'];
請求先到gqlErrorHandler,再到graphql。
響應先從graphql,再到gqlErrorHandler。app
gqlErrorHandler中間件代碼參考以下框架
const NOTFOUND = 404; const NORMAL = 200; module.exports = () => async function notFoundHandler(ctx, next) { // console.log('中間件通過'); await next(); // console.log('中間件notFoundHandler錯誤攔截', ctx.status, ctx.request.url); if (ctx.status !== NORMAL && ctx.request.url.indexOf('/gql/') > -1) { ctx.body = { success: false, message: 'gql解析錯誤', data: null }; ctx.status = NORMAL; } if (ctx.status === NOTFOUND) { ctx.body = { code: NOTFOUND, message: 'Not Found' }; } };
若是某個中間件執行異常,會跳過剩下的中間件,直接拋出該異常。
這時須要框架層面的捕獲。異步
// config.[env].js exports.onerror = { all(err, ctx){ // console.log('框架錯誤攔截',err); if(ctx.request.url.indexOf('/gql/')>-1 && ctx.response.status !== 200){ // console.log('捕獲住了gql錯誤'); ctx.set({ "Content-Type": "application/json" }); ctx.status = 200; ctx.body = JSON.stringify({ data:null, message:'gql解析錯誤', success: false }); } else{ ctx.status = 400; ctx.body = 'error'; } } }