GraphQL 是一种用于 API 的查询语言,它提供了一种更高效、强大和灵活的方式来获取和更新数据。在实际应用中,当客户端发送的 GraphQL 请求存在错误时,如何进行处理是一个非常重要的问题。本文将介绍 GraphQL 中错误请求的处理方式,包括错误类型、错误处理和错误提示,旨在帮助前端开发者更好地理解和使用 GraphQL。
错误类型
GraphQL 中的错误可以分为两种类型:语法错误和运行时错误。
语法错误
语法错误是指客户端发送的 GraphQL 请求不符合 GraphQL 规范,无法被服务器正确解析。常见的语法错误包括:
- 未闭合的括号、引号等
- 没有正确的查询语句
- 查询语句中使用了未定义的变量
- 查询语句中包含了不支持的操作
如果客户端发送的请求存在语法错误,服务器将返回一个 400 Bad Request 响应,并在响应体中包含错误信息。
运行时错误
运行时错误是指客户端发送的 GraphQL 请求符合 GraphQL 规范,但在服务器执行时出现了错误。常见的运行时错误包括:
- 查询的字段不存在
- 查询的参数类型不正确
- 访问未授权的数据
- 数据库连接失败
如果客户端发送的请求存在运行时错误,服务器将返回一个 200 OK 响应,并在响应体的 errors 字段中包含错误信息。
错误处理
GraphQL 中的错误处理可以分为两个层面:服务器层面和客户端层面。
服务器层面
在服务器层面,错误处理主要包括以下几个方面:
1. 异常捕获
在服务器端执行 GraphQL 查询时,可能会抛出异常。为了避免异常导致服务器崩溃,我们需要在代码中对异常进行捕获和处理。例如,在 Express 中,可以使用 try-catch 语句捕获异常,并返回一个包含错误信息的响应。
// www.javascriptcn.com code example
app.post('/graphql', async (req, res) => {
try {
const { query, variables } = req.body;
const result = await graphql(schema, query, rootValue, context, variables);
res.send(result);
} catch (err) {
res.status(500).send({
errors: [{
message: err.message,
stack: err.stack.split('\n')
}]
});
}
});2. 错误处理中间件
除了在代码中捕获异常外,还可以使用错误处理中间件来统一处理错误。错误处理中间件是一个 Express 中间件,它会在发生错误时被调用,并返回一个包含错误信息的响应。例如:
app.use((err, req, res, next) => {
res.status(500).send({
errors: [{
message: err.message,
stack: err.stack.split('\n')
}]
});
});3. 自定义错误类型
在 GraphQL 中,我们可以自定义错误类型,并在查询中返回。自定义错误类型通常包含错误代码、错误信息和错误详情等信息。例如:
// www.javascriptcn.com code example
const { GraphQLError } = require('graphql');
const MyErrorType = new GraphQLError('MY_ERROR', 'My error message', {
details: 'My error details'
});
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
myQuery: {
type: GraphQLString,
resolve: () => {
throw MyErrorType;
}
}
}
})
});在查询中返回自定义错误类型时,需要在错误处理中间件中将错误信息转换为 GraphQL 规范的格式。例如:
// www.javascriptcn.com code example
app.use((err, req, res, next) => {
const { errors } = err;
res.status(200).send({
data: null,
errors: errors.map(error => ({
message: error.message,
extensions: error.extensions
}))
});
});客户端层面
在客户端层面,错误处理主要包括以下几个方面:
1. 错误提示
当客户端发送的 GraphQL 请求存在错误时,我们需要在界面上给用户一个明确的错误提示。错误提示应该包含错误信息、错误代码和错误详情等信息,以便用户更好地理解和解决问题。
2. 错误重试
如果客户端发送的 GraphQL 请求因为网络原因或服务器问题失败了,我们可以在界面上提供错误重试功能。错误重试功能可以让用户重新发送请求,以便获取正确的数据。
3. 错误日志
除了在界面上提示错误外,我们还可以在客户端记录错误日志,以便分析和解决问题。错误日志应该包含错误信息、错误堆栈和错误发生的时间等信息,以便更好地定位和解决问题。
示例代码
以下是一个使用 Express 和 GraphQL 的示例代码,演示了如何处理 GraphQL 请求中的错误。
// www.javascriptcn.com code example
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');
const schema = buildSchema(`
type Query {
hello(name: String): String
}
`);
const rootValue = {
hello: ({ name }) => {
if (!name) {
throw new Error('Name is required');
}
return `Hello, ${name}!`;
}
};
const app = express();
app.use(express.json());
app.use('/graphql', graphqlHTTP({
schema,
rootValue,
graphiql: true,
customFormatErrorFn: (err) => ({
message: err.message,
code: err.extensions.code,
details: err.extensions.details,
stack: err.stack.split('\n')
})
}));
app.use((err, req, res, next) => {
const { errors } = err;
res.status(200).send({
data: null,
errors: errors.map(error => ({
message: error.message,
code: error.extensions.code,
details: error.extensions.details
}))
});
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});在上面的示例代码中,我们定义了一个名为 hello 的查询,它接受一个名为 name 的参数。如果客户端没有提供 name 参数,则会抛出一个错误。
在错误处理中间件中,我们将错误信息转换为 GraphQL 规范的格式,并返回给客户端。客户端可以根据返回的错误信息,进行错误提示、错误重试和错误日志记录等操作。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d186cda941bf7134334bcf