web-dev-qa-db-ja.com

GraphQLでエラーを処理して応答を送信する方法

私はGraphQLで始めていましたが、GraphQLでエラーをスローする方法を理解できませんでした

Webでいくつかの記事を読みましたが、それらのほとんどすべてが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)
      }
    }
  }
}
10
anny123

私のプロジェクトの1つで直面したことは、応答のステータスコードを設定するのが難しいことです。したがって、 express-graphql を使用して正しいstatusCodeを特定するために、いくつかのカスタムエラーレスポンスを作成しました

以下は例です(私が私のプロジェクトの1つで使用したもの):

--------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 を参照できます。

この助けを願っています!

2
Hardik Shah

graphqlは、すべきではないアプリケーションレベルのレイヤーである必要があります(最後の段落を参照すべきでない理由ではなくしない)には、httpが必要です。 99%のケースではhttpの上で実行されますが、その実行は非常に便利であるため、graphql自体がレイヤー7プロトコルです。

あなたの場合それはどういう意味ですか?まあ、それはあなたがHTTP/RESTからの概念をgraphqlからの概念と混合して後者に焦点を当てるべきではないことを意味します。ヘッダーエラーコードはHTTP/RESTの概念であり、graphqlは応答のerrorsフィールドでエラーを送信し、nodejs実装はすべてのエラーをすでにキャッチしてリストに追加しています。 HTTPステータスは常に200であり、クライアントはRESTとgraphqlの組み合わせではなく、graphql apiを気にして消費するべきではありません。

さて、言われているように、REST over HTTPの方が優れている点がいくつかあります。そのため、Apolloの開発者を含む人々も、主にgraphql標準が完全ではないため、やや混合した概念です(別名、APIの作成中に発生する可能性のあるすべての問題を解決するための標準/ルールがないため)人々は即興です。正直なところ、深刻なプロジェクトにはgraphqlはまだお勧めしません。 HTTP経由でRESTに固執するだけです。

参考

2
Valentin Radu