Apollo 中的异常处理

2,182 阅读2分钟

项目开发中,我们需要通过具体的error信息来告知前端如何处理报错逻辑,比如登录过期,需要前端退出登录,清除登录token等

最近在找一个关于error上报的问题,把看到的一些资料整理了一下

项目架构: 前端使用GATSBY框架,server因为配合的是 koa, 所以主要使用的是 apollo-server-koa

GraphQLError

graphql 中的 GraphQLError 继承自 node的Error类

class GraphQLError extends Error {
  constructor(
    message: string,
    nodes?: ReadonlyArray<ASTNode> | ASTNode | undefined,
    source?: Maybe<Source>,
    positions?: Maybe<ReadonlyArray<number>>,
    path?: Maybe<ReadonlyArray<string | number>>,
    originalError?: Maybe<Error>,
    extensions?: Maybe<{ [key: string]: any }>,
  )
  --- the rest code  ---
}  

ApolloError

ApolloError 继承自Error 按照GraphQLError 的定义实现

// class ApolloError extends Error implements GraphQLError {

class ApolloError extends Error {
    constructor(message, code, properties) {
        super(message);
        if (properties) {
            Object.keys(properties).forEach(key => {
                this[key] = properties[key];
            });
        }
        if (!this.name) {
            Object.defineProperty(this, 'name', { value: 'ApolloError' });
        }
        this.extensions = { code };
    }
}

ApolloError 可接受三个参数,message, code, properties

前端根据server定义的不同的code来处理不同的逻辑

    switch (code) {
        case 'WYB':
          alert('无感')
          break;
        default:
          alert('无羁')
          break;
    }

stacktrace

堆栈跟踪

在前端页面我们log出error信息,可以看到此参数,这个就类似 error.stack 的堆栈跟踪

每一行都以 "at " 开头。 每一帧描述了一个代码中导致错误生成的调用点

如果不想进行错误帧上报,可以在applo-serve中关闭

new ApolloServer ({ debug: false })

formatError

格式化ERROR

如果需要批量处理error信息,可以在此方法中操作。比如添加error日志警告功能等

new ApolloServer ({ 
    formatError: err => {
      console.log('请进行错误日志上报')
      return err
    }
})

这里可以改写error,比如添加一些属性,也可以直接返回error

几种常见的Error

apollo 有帮助我们创建了几种常见的Error对象,可在不同的业务场景中使用,他们全都是继承自 ApolloError ,只不过是将 name 属性重新命名

AuthenticationError

身份验证报错

export class AuthenticationError extends ApolloError {
  constructor(message: string) {
    super(message, 'UNAUTHENTICATED');

    Object.defineProperty(this, 'name', { value: 'AuthenticationError' });
  }
}

接受的参数是 message,可以外部传入,但是code参数是指定的 UNAUTHENTICATED

应用场景:用户身份有问题

if (!authorization) throw new AuthenticationError('You must be logged in')

报错的code为 UNAUTHENTICATED

前端输出一下此时的error

UserInputError

用户输入信息报错

export class UserInputError extends ApolloError {
  constructor(message: string, properties?: Record<string, any>) {
    super(message, 'BAD_USER_INPUT', properties);

    Object.defineProperty(this, 'name', { value: 'UserInputError' });
  }
}

一般在检查form表单字段的时候,如果不满足条件,可以上报此error

接受两个参数,message 和 properties

报错的code为 BAD_USER_INPUT

前端输出一下此时的error

ValidationError

参数检验报错

export class ValidationError extends ApolloError {
  constructor(message: string) {
    super(message, 'GRAPHQL_VALIDATION_FAILED');

    Object.defineProperty(this, 'name', { value: 'ValidationError' });
  }
}

报错的code为 GRAPHQL_VALIDATION_FAILED

前端输出一下此时的error

资料