【问题标题】:Graphql/Apollo Errors output sometimes data: null sometimes data: { function: null}Graphql/Apollo 错误输出有时数据:空有时数据:{函数:空}
【发布时间】:2019-09-16 20:25:10
【问题描述】:

我正在为我的 graphql 设置测试。这样做时,我意识到有时错误情况下的数据对象会像这样输出:

{
   errors: [...],
   data: null
}

有时:

{
     errors: [...],
     data: {
        updateCity: null
    }
}

那些测试是关于突变的。这是两个代码的示例:

解析器案例1:

 updateUser(parent, args, context, info) {
      logger.debug('Mutation > updateUser resolver');
      return userController.user.update.user(parent, args.userInfo, context, info);
    },

模式案例1:

extend type Mutation {
    updateUser(userInfo: UserInfo!): User!
}

控制器案例1:

user: async (parent, args, context, info) => {
    try {
      logger.debug('User Controller : update User');
      await controller.validate(args);
      const userModel = new UserModel('member');
      if (!(await userModel.findOne(args.id))) errorscb.userInputError('User does not exist');
      let id = args.id;
      let newArgs = args;
      delete newArgs.id;
      return userModel.updateById(id, newArgs);
    } catch (e) {
      logger.warn({ stack: e.stack, message: e.message });
      throw e;
    }
  },

模式案例2:

extend type Mutation {

    updateCity(id: Int!, name: String, countryId: Int): City
}

解析器案例2:

updateCity(obj, args, context, info) {
      logger.info('City > updateCity resolver');
      return cityController.city.update.city(obj, args, context, info);
    },

控制器案例 2:

city: async (parent, args, context, info) => {
    try {
      logger.info('City Controller : update city');

      await controller.validate(args);
      const cityModel = new CityModel('city');
      if (!(await cityModel.findOne(args.id))) 
          errorscb.userInputError('City does not exist');
      let id = args.id;
      let newArgs = args;
      delete newArgs.id;
      return cityModel.updateById(id, newArgs);
    } catch (e) {
      logger.warn({ stack: e.stack, message: e.message });
      throw e;
    } 

我想获得一致的输出,有人知道如何解决吗?

【问题讨论】:

    标签: node.js graphql graphql-js apollo-server


    【解决方案1】:
    extend type Mutation {
        updateUser(userInfo: UserInfo!): User!
    }
    

    找到了解决方法,不需要用户并且删除感叹号解决了我的问题(嗯...不知何故)

    updateUser(userInfo: UserInfo!): 用户!

    【讨论】:

      【解决方案2】:

      这实际上是预期的行为。

      你的updateUserupdateCity的区别在于后者返回一个可空类型(City),而前者返回一个非空类型(User!)。响应的不同之处在于错误会在响应中传播,直到它们到达可为空的字段。来自spec

      如果在解析字段时抛出错误,则应将其视为该字段返回 null,并且必须将错误添加到响应中的“错误”列表中。

      如果解析字段的结果为 null(因为解析该字段的函数返回 null 或发生错误),并且该字段是 Non-Null 类型,则抛出字段错误。错误必须添加到响应中的“错误”列表中。

      ...

      由于 Non-Null 类型的字段不能为 null,因此字段错误会被传播以由父字段处理。如果父字段可能为 null 则解析为 null,否则如果为 Non-Null 类型,则字段错误进一步传播到其父字段。

      换句话说,通过在字段解析期间抛出错误,我们有效地将该字段解析为 null。但是当我们告诉 GraphQL 一个字段具有 Non-Null 类型,并且该字段解析为 null 时,GraphQL 无法返回具有 null 值的字段(因为这会破坏模式的契约)。所以它使整个 parent 字段为空。如果父字段也是不可为空的,则该字段的父字段为空,依此类推...直到它到达可空字段或请求的根(data 字段)。

      比较:架构 1

      type Query {
        a: A
      }
      
      type A {
        b: B
      }
      
      type B {
        c: String
      }
      

      架构 2

      type Query {
        a: A
      }
      
      type A {
        b: B
      }
      
      type B {
        c: String!
      }
      

      架构 3

      type Query {
        a: A!
      }
      
      type A {
        b: B!
      }
      
      type B {
        c: String!
      }
      

      如果我们请求字段c,并且字段c的解析器抛出,响应如下:

      架构 1

      {
        "data": {
          "a": {
            "b": {
              "c": null
            }
          }
        }
      }
      

      架构 2

      {
        "data": {
          "a": {
            "b": null
          }
        }
      }
      

      架构 3

      {
        "data": null
      }
      

      【讨论】:

        猜你喜欢
        • 2020-08-04
        • 1970-01-01
        • 2020-02-15
        • 2019-11-01
        • 1970-01-01
        • 2015-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多