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