GraphQL 是一种用于构建 API 的查询语言,其允许客户端明确地请求需要的数据。GraphQL 的流行程度一直在上升,使得开发者们不得不更加重视如何处理错误。在 GraphQL 中,处理错误的方法之一是使用错误解析器(Error Resolver),它允许我们拦截错误,并返回自定义错误消息给客户端。
在本文中,我们将深入研究如何在 GraphQL 解析器中捕获错误,并返回自定义错误消息。我们将涵盖以下主题:
- 错误解析器是什么
- 如何创建错误解析器
- 如何捕获错误并返回自定义错误消息
- 示例代码
1. 错误解析器是什么
在 GraphQL 的查询执行过程中,错误解析器(Error Resolver)是一个特殊的函数,它会被调用以处理错误,并返回带有自定义错误消息的 GraphQL 错误。
错误解析器是通过提供一个对于查询执行中可能出现的任何错误进行扩展的机制来实现的。如果我们没有提供错误解析器,那么 GraphQL 默认会返回一个非常简单的错误消息,例如“Unexpected error”。
可以通过在 GraphQL 构架中注册错误解析器来自定义错误消息。在错误解析器中,我们可以检查发生的错误,并根据需要返回自定义错误消息。
2. 如何创建错误解析器
我们可以通过一些方法创建一个错误解析器。以下是创建错误解析器的步骤:
1)通过入口文件注册错误解析器:
// www.javascriptcn.com code example
import { ApolloServer } from 'apollo-server';
import { MyResolver } from './resolver';
import { MyError } from './error';
import { MyErrorHandler } from './error-handler';
const server = new ApolloServer({
typeDefs: schema,
resolvers: [MyResolver],
formatError: MyErrorHandler,
});其中,“MyErrorHandler”是我们所注册的错误解析器。在这个例子里,我们的错误解析器定义为类“MyErrorHandler”的静态方法“formatError”。
2)定义错误解析器:
// www.javascriptcn.com code example
export class MyErrorHandler {
static formatError(error) {
if (error.originalError instanceof MyError) {
return { message: error.message, code: error.originalError.code };
}
return error;
}
}我们可以通过检查error.originalError的类型,来捕获我们定义的自定义错误。在上面的例子中,我们从自定义错误对象MyError中提取错误代码,并且以此构建一个新的错误数组。最后,我们返回带有自定义错误消息的 GraphQL 错误。
3. 如何捕获错误并返回自定义错误消息
在我们定义好错误解析器之后,我们还需要在解析器内部捕获错误,并返回自定义错误消息。以下是捕获错误并返回自定义错误消息的步骤:
// www.javascriptcn.com code example
export const MyResolver = {
Query: {
getRecord(root, { id }) {
const record = fetchRecordById(id);
if (record) {
return record;
}
throw new MyError('Record not found', 'NOT_FOUND');
},
},
};其中,“MyError”是我们自己定义的一个自定义错误类,其包含错误的详细信息。
在以上代码中,我们尝试通过 ID 获取记录。如果找到了记录,我们返回记录。如果找不到记录,我们会抛出一个自定义错误对象。
另外需要注意的是,如果抛出的错误是由于用户提供了错误的查询参数,那么错误可能是语法错误(Syntax Error)或变量错误(Variable Error)。这时我们需要调用GraphQLBaseError类的createLocatedError()来构建错误对象。例如:
// www.javascriptcn.com code example
import * as graphql from 'graphql';
import { ApolloError } from 'apollo-server';
export class MyErrorHandler {
static formatError(error) {
if (error.originalError) {
const isOperationalError = (error.originalError instanceof MyError);
if (isOperationalError) {
return new ApolloError(error.message, error.originalError.code);
}
}
const locatedError = graphql.GraphQLBaseError.createLocatedError(error);
return new ApolloError(locatedError.message, 'INTERNAL_SERVER_ERROR');
}
}在我们捕获错误之后,我们需要返回一个包含自定义错误消息的错误对象。在上面的代码中,我们检查是否抛出了自定义错误对象。如果抛出了自定义错误对象,我们将构建一个 ApolloError(在 ApolloServer 中使用的错误对象),并且返回自定义的错误消息和状态码。否则,我们构建一个包含默认错误消息和状态码的 ApolloError。
示例代码
下面是基于 Express 框架的具体示例代码。以下是实现错误解析器的代码:
// www.javascriptcn.com code example
import { ApolloError } from 'apollo-server-express';
export class MyErrorHandler {
static formatError(error) {
if (error.message.startsWith('Access forbidden')) {
throw new ApolloError(error.message, 'FORBIDDEN');
}
throw new ApolloError('Internal error', 'INTERNAL_ERROR');
}
}错误解析器先判断错误消息中是否包含“Access Forbidden”这个字符串。如果包含,它就返回一个 ApolloError 对象,带有状态码“FORBIDDEN”。否则,它返回一个 ApolloError 对象,带有状态码“INTERNAL_ERROR”。
以下是错误订阅的示例代码:
// www.javascriptcn.com code example
export const MyResolver = {
Mutation: {
subscribe(root, { email }) {
const success = true;
if (!success) {
throw new Error('User subscription failed');
}
throw new MyError('Access forbidden');
},
},
};这是一个 subscription 解析器,它调用一个订阅服务,并返回一个成功/失败标志。如果订阅失败,我们抛出一个普通的错误。否则,我们抛出一个自定义错误对象。
到这里,我们已经可以在 GraphQL 解析器中捕获错误,并返回自定义错误消息了。本文介绍了如何创建错误解析器、捕获错误,并返回自定义错误消息。我们的示例代码可以帮助您更好地理解其中的细节。尽管 GraphQL 本身非常灵活,但是在正确的情况下使用错误解析器,可以让您轻松地处理查询错误,并为客户端返回友好的错误消息。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d6638da941bf7134c20c10