開発者ドキュメント

GraphQLのミューテーションとサブスクリプション

この記事では、 MutationSubscription GraphQLでクエリを実行するだけでなく、データを操作して変更を監視するタイプ。 公式ドキュメントで詳細をお気軽に見つけてください。

簡単にするために、データベースやHTTPリクエストは使用しませんが、スキーマとリゾルバーを使用して基本的なAPIを設定する方法を知っている必要があります。

インストール

graphql-yogaライブラリを使用してサーバーをセットアップします nodemon 自動的にリロードします。 また、JavaScriptの最新機能を使用できるように、Preprosbabelなどのプリプロセッサーも必要です。

$ npm i graphql-yoga nodemon

ボイラープレートの設定

サーバーのセットアップに加えて、空の users 配列と、すべてのユーザーを返すための単純なスキーマとリゾルバー。

server.js
import { GraphQLServer } from 'graphql-yoga'

const users = [];

const typeDefs = `
  type Query {
    users: [User!]!
  }

  type User {
    name: String!
    age: Int!
  }
`;

const resolvers = {
  Query: {
    user() {
      return users;
    }
  }
}

const server = new GraphQLServer({ typeDefs, resolvers });

server.start(() => console.log('server running'));

必要です start 出力ファイルでnodemonを実行するスクリプト:

package.json
{
  "name": "graphql-api",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "dependencies": {
    "graphql-yoga": "^1.16.7"
  },
  "devDependencies": {
    "nodemon": "^1.19.1"
  },
  "scripts": {
    "start": "nodemon server-dist.js"
  },
  "author": "",
  "license": "ISC"
}

今ターミナルであなたはただ走ることができます npm run start.

以上で localhost:4000 GraphQLPlaygroundを起動して実行する必要があります。 user { name } 空の配列を返します。

ミューテーションを作成する

ミューテーションの構文は、クエリの構文とほぼ同じです。 必要なオプションを宣言し、引数(存在する場合)を追加し、完了時に返されるタイプを宣言するだけです。

すべてのout引数をインラインで追加する代わりに、データをと呼ばれる独自の特殊な型に分割することはかなり一般的です。 input 整理のために入力します。 これは、 Prisma などのツールで見られる一般的な命名規則であり、リゾルバーがinputという単語で終わるものに関係なく、入力に名前を付けます。 addUser 取得します AddUserInput 入力。

server.js
const typeDefs = `
  type Mutation {
    addUser(data: AddUserInput): User!
  }

  input AddUserInput {
    name: String!, 
    age: Int!
  }
`;

クエリの場合と同様に、上の引数にアクセスできます args 新しいユーザーを配列に追加して、それらを返します。

const resolvers = {
  Query: {...},
  Mutation: {
    addUser(parent, args, ctx, info) {
      const user = { ...args.data };

      users.push(user);
      return user;
    }
  }
}

ミューテーションの削除と更新

構文が非常に単純なため、他のCRUD操作を具体化するのはほとんど簡単です。

名前でユーザーを検索するだけで、削除または更新するアイテムがわかります。

server.js
const typeDefs = `
  type Mutation {
    deleteUser(name: String!): User!
    updateUser(name: String!, data: UpdateUserInput): User!
  }

  input UpdateUserInput {
    name: String
    age: Int
  }
`

const resolvers = {
  Query: { ... },
  Mutation: {
    deleteUser(parent, args, ctx, info) {
      // We're just finding the index of the user with a matching name,
      // checking if it exists, and removing that section of the array.
      const userIndex = users.findIndex(user => user.name.toLowerCase() === args.name.toLowerCase());
      if (userIndex === -1) throw new Error('User not found');

      const user = users.splice(userIndex, 1);
      return user[0];
    },
    updateUser(parent, args, ctx, info) {
      const user = users.find(user => user.name.toLowerCase() === args.who.toLowerCase());
      if (!user) throw new Error('User not found');

      // This way, only the fields that are passed-in will be changed.
      if (typeof args.data.name === "string") user.name = args.data.name;
      if (typeof args.data.age !== "undefined") user.age = args.data.age;

      return user;
    }
  }
}

今で終わり localhost:4000 このミューテーションを試して、配列を再度クエリできます。

mutation {
  addUser(data: {
    name: "Alli",
    age: 48
  }) {
    name
    age
  }
}

または別のタブで:

mutation {
  updateUser(name: "Alli", data: {
    name: "Crusher",
    age: 27
  }) {
    name
    age
  }
}

サブスクリプション

スペシャルが使えます Subscription データの変更を監視するために入力します。 構文はクエリやミューテーションの構文と非常に似ていますが、タイプを追加するだけです Subscription、見たいものと、返したいものを追加します。 変更されたデータと、それが作成、削除、または更新のいずれの操作であったかを通知するカスタムタイプを返します。

サブスクリプションを使用するには、使用する必要があります PubSub graphql-yogaから、他のすべての前に初期化します。 サブスクリプションリゾルバーでは、次の関数を使用します subscribe 非同期イベントを返す必要があります。これに名前を付けます user. このサブスクリプションに何かを接続する場合は常に、このイベント名を使用します。

server.js
import { GraphQLServer, PubSub } from 'graphql-yoga';

const pubsub = new PubSub();

const typeDefs = `
type Subscription {
  user: UserSubscription!
}

type UserSubscription {
  mutation: String!
  data: User!
}
`

const resolvers = {
  Query: { ... },
  Mutation: { ... },
  Subscription: {
    user: {
      subscribe() {
        return pubsub.asyncIterator('user');
      }
    }
}
}

サブスクリプション自体はセットアップされており、生成されたGraphQLドキュメントで利用できますが、いつ起動するか、何を返すかはわかりません。 ミューテーションに戻って、追加します pubsub.publish 私たちにリンクするには user イベントを行い、データを返します。

const resolvers = {
  Query: { ... },
  Mutation: {
    addUser(parent, args, ctx, info) {
      const user = { ...args.data };

      users.push(user);

      // We'll just link it to our user event,
      // and return what type of mutation this is and our new user.
      pubsub.publish("user", {
        user: {
          mutation: "Added",
          data: user
        }
      });

      return user;
    },
    deleteUser(parent, args, ctx, info) {
      const userIndex = users.findIndex(
        user => user.name.toLowerCase() === args.who.toLowerCase()
      );
      if (userIndex === -1) throw new Error("User not found");

      const user = users.splice(userIndex, 1);

      pubsub.publish("user", {
        user: {
          mutation: "Deleted",
          data: user[0]
        }
      });

      return user[0];
    },
    updateUser(parent, args, ctx, info) {
      const user = users.find(
        user => user.name.toLowerCase() === args.who.toLowerCase()
      );
      if (!user) throw new Error("User not found");

      if (typeof args.data.name === "string") user.name = args.data.name;
      if (typeof args.data.age !== "undefined") user.age = args.data.age;

      pubsub.publish("user", {
        user: {
          mutation: "Updated",
          data: user
        }
      });

      return user;
    }
  },
  Subscription: { ... }
};

以上で localhost:4000 新しいタブを開いて、次のサブスクリプションを実行できます。 小さな糸車で「聞いている…」というメッセージが表示されるはずです。 別のタブで、他の過去のミューテーションを実行できるようになりました。サブスクリプションは、実行された内容と変更された内容を自動的に返します。

subscription {
  user {
    mutation
    data {
      name
      age
    }
  }
}

結論

これが、ミューテーションとサブスクリプションを使用してGraphQLAPIをセットアップする方法を理解するのに役立つことを願っています。 これを設定する際に問題が発生した場合は、いつでもこのリポジトリを確認できます。

モバイルバージョンを終了