egg
egg copied to clipboard
获取egg-graphql中业务代码抛出的异常
发现graphql请求触发的业务逻辑所抛出的异常都被捕获了,不知道如何获取Error对象,控制台和相关日志找了一圈也没看到。 有什么办法能够获取这些Error么?
使用try……catch也无法捕获吗?请问目前你的代码是?
单独对出错代码try catch是可以捕获的,想要在外层统一拦截。
萌新同问,如果想要在做统一封装拦截有什么方案吗。现在发现graphql的报错不会走到egg-error的拦截中,(即使是代码层面的报错)也会被统一拦截到了前端,只能一个个去加try...catch。 稍微看了一下源码,好像是有统一做try{}catch{}然后返回给前端,请问能否在这里切入提供一个函数方便自定义处理呢。
如果是egg-graphql 2.0以下版本,可以将插件中间件复制到项目下修改,覆盖插件里的中间件,具体修改配置graphqlKoa时带上formatError,在formatError中做错误的统一处理。 2.0+之后,同样的方式不灵了因为graphqlKoa api修改了,formatError只能在定义server的时候定义。
首先感谢大佬回复,不过这里提到的formateError只能在定义server的时候定义能否具体描述一下呢。我看源码里面是直接引用了graphql的方法来进行报错,好像并没有提供出定义的位置...以及这样做怎样和resetApi时的报错中间件能结合起来使用也是比较疑惑的点
@SingleMai
egg-egg-graphql 1.x版本
egg-egg-graphql 1.x版本对应的apollo-server-koa是1.x,下面是apollo-server-koa 1.x的官方demo: https://github.com/apollographql/apollo-server/blob/v1.4.0/packages/apollo-server-koa/README.md
import koa from 'koa'; // koa@2
import koaRouter from 'koa-router';
import koaBody from 'koa-bodyparser';
import { graphqlKoa } from 'apollo-server-koa';
const app = new koa();
const router = new koaRouter();
const PORT = 3000;
// koaBody is needed just for POST.
app.use(koaBody());
router.post('/graphql', graphqlKoa({ schema: myGraphQLSchema }));
router.get('/graphql', graphqlKoa({ schema: myGraphQLSchema }));
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(PORT);
如果要增加错误统一处理:
router.post('/graphql', graphqlKoa({ schema: myGraphQLSchema, formateError: func... }));
egg-egg-graphql 1.x插件中间件的使用是 https://github.com/eggjs/egg-graphql/blob/1.3.0/app/middleware/graphql.js
return graphqlKoa({
schema: app.schema,
context: this,
})(this);
这样没有办法直接传 formateError 参数。
所以我才说
如果是egg-graphql 2.0以下版本,可以将插件中间件复制到项目下修改,覆盖插件里的中间件,具体修改配置graphqlKoa时带上formatError,在formatError中做错误的统一处理。
egg-egg-graphql 2.x版本
egg-egg-graphql 2.x版本对应的apollo-server-koa是2.x,下面是apollo-server-koa 2.x的官方demo: https://github.com/apollographql/apollo-server/blob/master/packages/apollo-server-koa/README.md
const Koa = require('koa');
const { ApolloServer, gql } = require('apollo-server-koa');
// Construct a schema, using GraphQL schema language
const typeDefs = gql`
type Query {
hello: String
}
`;
// Provide resolver functions for your schema fields
const resolvers = {
Query: {
hello: () => 'Hello world!',
},
};
const server = new ApolloServer({ typeDefs, resolvers });
const app = new Koa();
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () =>
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`),
);
如果要增加错误统一处理:
const server = new ApolloServer({ typeDefs, resolvers, formateError: func ... });
egg-egg-graphql 2.x插件中间件的使用是 https://github.com/eggjs/egg-graphql/blob/2.3.0/app/middleware/graphql.js
return graphqlKoa({
schema: app.schema,
context: this,
})(this);
这里的 graphqlKoa 即使传入 formateError 参数也没办法了。
对于“怎样和resetApi时的报错中间件能结合起来使用” 我们这边没有这样的场景,我们是的做了个graphql单独的服务,graphql服务的后面是后台接口等(包括其他数据来源),graphql服务提供服务给前台服务端或前台客户端。
感谢回复, so噶 抱歉最近有点太忙了 一直没上来看。大佬解释得非常清晰,算是理清了很多疑惑非常感谢!!
我把这个 formateError 透出一下
https://github.com/eggjs/egg-graphql/pull/24 跟进
eggjs/egg-graphql#24 一直没有进展吗? @jtyjty99999
egg中有两个地方可以捕捉egg-graphql的解析错误或者内部错误。
- 中间件
exports.middleware = ['errorHandler','graphql'];
- 另一个是框架层面的onerror。
exports.onerror = {
all(err, ctx){
if(ctx.request.url.indexOf('/graphql')>-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';
}
}
}
我很高兴自己解决了这个问题,在这里分享一下。
标题中说捕获graphql中业务代码的异常,而自己的业务代码都是写在resolver中的,也就是说,如果可以在resolver执行前首先执行类似 try{ } catch(err){ }
这样的代码,把resolver的实际执行放在 try{ }
代码段中,即可实现捕捉graphql异常。
所有resolver都可以在app.schema
中获取到,那么就可以实现上述所说。
不仅如此,我还把它扩展成了类似中间件一样的机制,这样就可以有更多的玩法。
请参考下面项目的README介绍中的 resolver中间件 章节