如何在GraphQL中处理错误并发送响应

时间:2019-08-03 21:39:37

标签: javascript node.js graphql

我从GraphQL开始,却无法理解如何在GraphQL中引发错误

我在网上浏览了几篇文章,但是几乎所有文章都使用Apollo,并且代码结构看起来与我的工作方式大不相同。

考虑这段代码,在这里我要进行突变,现在如何发送有错误的响应消息并在发生错误的情况下更改标头状态消息?

  AddNewPersonalInfo: {
  type: userDashboardType,
  args: { 
    parameter: {
      type: userCreationlInputType
    }
  }, 
  resolve: async (parent, args, context) => {
    args.parameter.userId = context.req.headers.userId
    //Check if user info already exsist
    const checkIfUserInformationExsist = await getSelectedThingFromTable('CatsWork_personal', 'userId', `${userId}`)
    if (checkIfUserInformationExsist[0]) {
      const error = {
        code: 403, 
        message: 'User info Already exsist'
      }
      throw new Error(error)
    } else {
      try {
      const addLinkedinUser = await insertIntheTable('personal', payload)
      return true
      } catch (err) {
        console.error(err)
        throw new Error(err)
      }
    }
  }
}

2 个答案:

答案 0 :(得分:2)

graphql应该是不应该(请参见上段为什么不应该而不是不需要)要求的应用程序层http上班。尽管在99%的情况下,它运行在http之上,但由于这样做很方便,graphql本身就是第7层协议。

这对您而言意味着什么?好吧,这意味着您不应该将HTTP / REST中的概念与graphql中的概念混为一谈。标头错误代码是HTTP / REST概念,graphql在响应的errors字段中发送错误,而nodejs实现已经捕获了所有错误并将其添加到列表中。 HTTP状态始终为200,并且您的客户端不必关心和使用您的graphql api,也不要将REST与graphql混合使用。

现在,可以这么说,基于HTTP的REST在某些方面做得更好。因此,包括Apollo的开发人员在内的人们也混为一谈,主要是因为graphql标准不完整(也就是,它没有解决在构建API时可能遇到的所有问题的标准/规则),所以人们即兴创作。老实说,对于任何严肃的项目,我都不会推荐graphql。去那里,这样做,不值得。只需坚持使用HTTP上的REST。

Reference

答案 1 :(得分:1)

我在一个项目中所面临的问题,很难设置响应的状态代码。因此,我进行了一些自定义错误响应,以使用express-graphql

标识正确的statusCode

下面是示例(我在一个项目中使用的内容):

-------- app.js file --------

const graphqlHTTP = require('express-graphql')

app.use('/graphql', (req, res) => {
  graphqlHTTP({
    schema: GraphQLSchema, //A GraphQLSchema instance from GraphQL.js. A schema must be provided.
    graphiql: true,
    context: { req },
    formatError: (err) => {
      const error = getErrorCode(err.message)
      return ({ message: error.message, statusCode: error.statusCode })
    }
  })(req, res)
})

-------- getErrorCode函数实现--------

const { errorType } = require('../constants')

const getErrorCode = errorName => {
  return errorType[errorName]
}

module.exports = getErrorCode

-------- Constant.js文件--------

exports.errorName = {
  USER_ALREADY_EXISTS: 'USER_ALREADY_EXISTS',
  SERVER_ERROR: 'SERVER_ERROR'
}

exports.errorType = {
  USER_ALREADY_EXISTS: {
    message: 'User is already exists.',
    statusCode: 403
  },
  SERVER_ERROR: {
    message: 'Server error.',
    statusCode: 500
  }
}

现在,我们可以使用我们的设置了。

从您的查询或变异中,您需要常量文件并返回自定义错误:

const { errorName } = require('../constant')

AddNewPersonalInfo: {
  type: userDashboardType,
  args: { 
    parameter: {
      type: userCreationlInputType
    }
  }, 
  resolve: async (parent, args, context) => {
    args.parameter.userId = context.req.headers.userId
    //Check if user info already exsist
    const checkIfUserInformationExsist = await getSelectedThingFromTable('CatsWork_personal', 'userId', `${userId}`)
    if (checkIfUserInformationExsist[0]) {
      const error = {
        code: 403, 
        message: 'User info Already exsist'
      }
      throw new Error(errorName.USER_ALREADY_EXISTS) // Here you can use error from constatnt file
    } else {
      try {
      const addLinkedinUser = await insertIntheTable('personal', payload)
      return true
      } catch (err) {
        console.error(err)
        throw new Error(errorName.SERVER_ERROR) // Here you can use error from constatnt file
      }
    }
  }
}

--------错误响应--------

{
  error: [{
    "statusCode": 403,
    "message": "User is already exists."
  }],
  data: null
}

我们也只需要从FS端编写自定义错误处理。

  

注意:-不推荐使用formatError:,而将其替换为customFormatErrorFn。它会在1.0.0版中删除。您可以参考customFormatErrorFn

希望获得帮助!