Graphql / Apollo Errors输出有时数据:null有时数据:{function:null}

问题描述 投票:2回答:2

我正在为我的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
2个回答
1
投票

这实际上是预期的行为。

updateUserupdateCity之间的区别在于后者返回可以为空的类型(City),而前者返回非空类型(User!)。响应的差异来自于错误在响应中传播直到它们到达可空字段的事实。来自spec

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

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

...

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

换句话说,通过在字段分辨率期间抛出错误,我们有效地将该字段解析为null。但是当我们告诉GraphQL一个字段有一个Non-Null类型,并且该字段解析为null时,GraphQL不能返回带有null值的字段(因为这会破坏模式的契约)。因此它使整个父字段为空。如果父字段也是非可空的,则它使该字段的父字段为空,依此类推......直到它到达可空字段或请求的根(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
}

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

找到修复,要求用户是不必要的并删除感叹号修复了我的问题(呃...不知何故)

updateUser(userInfo:UserInfo!):用户 !

© www.soinside.com 2019 - 2024. All rights reserved.