Open KeihakuOh opened 1 month ago
const graphql = require('graphql');
const axios = require('axios');
const {
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLSchema
} = graphql;
const CompanyType = new GraphQLObjectType({
name: 'Company',
fields: {
id: { type: GraphQLString },
name: { type: GraphQLString },
description: { type: GraphQLString }
}
});
const UserType = new GraphQLObjectType({
name: 'User',
fields: {
id: { type: GraphQLString },
firstName: { type: GraphQLString },
age: { type: GraphQLInt },
company: {
type: CompanyType,
resolve(parentValue, args) {
return axios.get(`http://localhost:3000/companies/${parentValue.companyId}`)
.then(res => res.data);
}
}
}
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
user: {
type: UserType,
args: { id: { type: GraphQLString } },
resolve(parentValue, args) {
return axios.get(`http://localhost:3000/users/${args.id}`)
.then(resp => resp.data);
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery
});
GraphQLObjectType: GraphQLの型を定義するためのオブジェクト GraphQLString: GraphQLにおける文字列型(String)を定義します GraphQLInt: GraphQLにおける整数型(Int)を定義します。
nameフィールド:このオブジェクト型の名前 argsフィールド: クライアントがuserフィールドをクエリする際に、引数(args)として渡すデータを定義しています。
ーーーーーー 実際の流れ: ステップ1: RootQueryの実行
{
user(id: "123") {
id
firstName
age
company {
id
name
description
}
}
}
この場合、まずRootQueryのuserフィールドのresolve関数が呼び出され、args.idが渡されてユーザー情報を取得します。
ステップ2: UserTypeのフィールドを解決 ユーザーデータが取得された後、GraphQLはクエリで指定されたフィールド(id、firstName、age、company)を1つずつ見ていきます。
UserTypeのフィールドに基づいてデータを返す: その際、UserTypeで定義されている各フィールド(id、firstName、age)について、クエリに含まれているかどうかを確認します。
もしクエリに含まれていれば、そのフィールドのデータを直接(graphql内部に)返します。 id、firstName、age はユーザーデータの中にすでに存在しているため、GraphQLは追加の処理をせずに、そのまま返します。
フィールドごとにresolve関数がある場合: companyフィールドのようにresolve関数が定義されている場合、そのresolve関数が実行されます(例: parentValue.companyIdを使って会社情報を取得する)。
parentValue とは何か?
// 親フィールドが user の場合、ここで parentValue はそのユーザーデータを保持している
console.log(parentValue); // => { id: "123", firstName: "John Doe", age: 28 }
parentValue は、親のフィールドがリゾルブされた結果が渡される値です。つまり、ネストされたクエリがある場合、親のデータを次のネストされたフィールドのresolve関数で参照できます。 parentValueを使うことで、ネストされたフィールド(例: orders)が、親フィールド(例: user)のデータに基づいて適切なデータを返すことができます。
const graphql = require('graphql');
const axios = require('axios');
const {
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLSchema
} = graphql;
const UserType = new GraphQLObjectType({
name: 'User',
fields: {
id: { type: GraphQLString },
firstName: { type: GraphQLString },
age: { type: GraphQLInt }
}
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
user: {
type: UserType,
args: { id: { type: GraphQLString } },
resolve(parentValue, args) {
return axios.get(http://localhost:3000/users/${args.id})
.then(resp => resp.data);
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery
});
GraphQLSchemaの中で RootQueryを指定していますが、RootQuery の中ではすでに UserType が参照されています。つまり、RootQuery をエクスポートすることで、自動的にUserTypeも参照される形になっています。
return axios.get(`http://localhost:3000/users/${args.id}`)
.then(resp => resp.data);
具体的な流れ axios.get()の呼び出し:
axios.get()は、指定されたURLに対してHTTP GETリクエストを送信します。このリクエストは非同期に行われ、Promiseオブジェクトがすぐに返されます。 Promiseが返された後:
Promiseオブジェクトは、その結果(成功または失敗)が返るまで保留状態になります。リクエストが成功すると、Promiseの状態は「解決済み(fulfilled)」になります。 .then()の実行:
リクエストが成功した後、.then()ブロックが実行され、resp(レスポンスオブジェクト)に対して処理が行われます。この場合、resp.data(レスポンスデータの本体部分)が抽出されて返されます。 resolve関数の戻り値としてPromiseが返る:
resolve関数の戻り値は最終的にPromiseオブジェクトです。GraphQLはこのPromiseが解決されるのを待ち、その結果をクライアントに返します。
.graphqlHTTPは、このモジュール内に含まれる関数で、GraphQL APIのミドルウェアとして使われます。このミドルウェアは、GraphQLのクエリを処理し、レスポンスを返す役割を持っています。
GraphiQLは、ブラウザ上で動作するGraphQLの「IDE」です。これは「Integrated Development Environment(統合開発環境)」の一種で、GraphQLのリクエストを送信し、レスポンスをリアルタイムで確認できるツールです。