Как правильно использовать подписку GraphQL?

У меня есть приложение на базе GraphQL. Части запроса и мутации работают хорошо. Я пытаюсь добавить подписку GraphQL.

Код части подписки на сервер GraphQL вдохновлен демонстрацией в файле readme apollographql/подписки-транспорт-ws.

Пожалуйста, также проверьте комментарии в коде для получения более подробной информации.

import Koa from 'koa';
import Router from 'koa-router';
import graphqlHTTP from 'koa-graphql';
import asyncify from 'callback-to-async-iterator';
import { SubscriptionServer } from 'subscriptions-transport-ws';
import firebase from 'firebase-admin';
import { execute, subscribe } from 'graphql';
import { GraphQLObjectType, GraphQLString } from 'graphql';

const MeType = new GraphQLObjectType({
  name: 'Me',
  fields: () => ({
    name: { type: GraphQLString },
    // ...
  }),
});

const listenMe = async (callback) => {
  // Below the firebase API returns real-time data
  return firebase
    .database()
    .ref('/users/123')
    .on('value', (snapshot) => {
      // snapshot.val() returns an Object including name field.
      // Here I tested is correct, it always returns { name: 'Rose', ... }
      // when some other fields inside got updated in database.
      return callback(snapshot.val());
    });
};

const Subscription = new GraphQLObjectType({
  name: 'Subscription',
  fields: () => ({
    meChanged: {
      type: MeType,
      subscribe: () => asyncify(listenMe),
    },
  }),
});

const schema = new GraphQLSchema({
  query: Query,
  mutation: Mutation,
  subscription: Subscription,
});

const app = new Koa();
app
  .use(new Router()
    .post('/graphql', async (ctx) => {
      // ...

      await graphqlHTTP({
        schema,
        graphiql: true,
      })(ctx);
    })
    .routes());

const server = app.listen(3009);

SubscriptionServer.create(
  {
    schema,
    execute,
    subscribe,
  },
  {
    server,
    path: '/subscriptions',
  },
);

Я использую Altair GraphQL-клиент для тестирования, так как он поддерживает подписку на GraphQL.

Как правильно использовать подписку GraphQL?

Как видно на скриншоте, он получает новые данные каждый раз, когда данные изменяются в базе данных.

Однако meChanged — это null, и он не выдает никаких ошибок. Есть идеи? Спасибо

Я не знаю, что означает всегда, и вы не включаете сообщение об ошибке с панели «Сеть» в Chrome Dev Tools, поэтому диагностика вашей проблемы затруднена. Однако вы смотрели на это: stackoverflow.com/questions/56319137/…

Preston 19.07.2019 03:43

@Престон Спасибо! Только что обновил заголовок. Я надеюсь, что смогу опубликовать сообщение об ошибке консоли Chrome, но я еще не начал создавать часть подписки для клиента, так как отсутствует документ об использовании подписки GraphQL без какой-либо структуры, такой как Apollo. Вот почему я использую клиент Altair GraphQL в качестве отправной точки, чтобы понять, как работает подписка на GraphQL.

Hongbo Miao 19.07.2019 04:07
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
7
2
2 208
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Наконец-то появилась новая библиотека, которая может выполнять работу без полноценного фреймворка Apollo.

https://github.com/enisdenjo/graphql-ws

Вот коды, которые у меня есть:

Сервер (язык определения схемы GraphQL)

import { useServer } from 'graphql-ws/lib/use/ws';
import WebSocket from 'ws';
import { buildSchema } from 'graphql';

const schema = buildSchema(`
  type Subscription {
    greeting: String
  }
`);

const roots = {
  subscription: {
    greeting: async function* sayHiIn5Languages() {
      for (const hi of ['Hi', 'Bonjour', 'Hola', 'Ciao', 'Zdravo']) {
        yield { greeting: hi };
      }
    },
  },
};

const wsServer = new ws.Server({
  server, // Your HTTP server
  path: '/graphql',
});
useServer(
  {
    schema,
    execute,
    subscribe,
    roots,
  },
  wsServer
);

Сервер (способ объекта GraphQL.js GraphQLSchema)

import { execute, subscribe, GraphQLObjectType, GraphQLSchema, GraphQLString } from 'graphql';
import { useServer } from 'graphql-ws/lib/use/ws';
import WebSocket from 'ws';
import { PubSub } from 'graphql-subscriptions';

const pubsub = new PubSub();

const subscription = new GraphQLObjectType({
  name: 'Subscription',
  fields: {
    greeting: {
      type: GraphQLString,
      resolve: (source) => {
        if (source instanceof Error) {
          throw source;
        }
        return source.greeting;
      },
      subscribe: () => {
        return pubsub.asyncIterator('greeting');
      },
    },
  },
});

const schema = new GraphQLSchema({
  query,
  mutation,
  subscription,
});

setInterval(() => {
  pubsub.publish('greeting', {
    greeting: 'Bonjour',
  });
}, 1000);

const wsServer = new ws.Server({
  server, // Your HTTP server
  path: '/graphql',
});
useServer(
  {
    schema,
    execute,
    subscribe,
    roots,
  },
  wsServer
);

Клиент

import { createClient } from 'graphql-ws';

const client = createClient({
  url: 'wss://localhost:5000/graphql',
});

client.subscribe(
  {
    query: 'subscription { greeting }',
  },
  {
    next: (data) => {
      console.info('data', data);
    },
    error: (error) => {
      console.error('error', error);
    },
    complete: () => {
      console.info('no more greetings');
    },
  }
);

РАСКРЫТЬ: я не связан с библиотекой.

Я попробовал первый сервер, т. Е. (Сервер (язык определения схемы GraphQL)) и клиентский код, поскольку он должен выполнять один POC, но я получил следующую ошибку: - «Поле подписки должно возвращать асинхронный итеративный объект. Получено: {}.». Не могли бы вы сообщить мне, что я могу делать неправильно, так как я нуб в подписках на graphql

sagg1295 19.05.2021 20:40

@ sagg1295 проверьте github.com/Hongbo-Miao/hongbomiao.com/blob/main/api/src/grap‌​hQL/…, это может вам помочь. Это полноценная рабочая демонстрация.

Hongbo Miao 19.05.2021 20:55

Спасибо за это. Я хочу прояснить одну вещь в приведенной выше ссылке, которую вы использовали модуль graphql-subscriptions. Нужно ли делать подписку, используя это? Разве мы не можем просто использовать graphql-ws, ws и graphql для выполнения подписок graphql? Поскольку я следовал коду, указанному на странице github graphql-ws. Это не сработало. Если хотите, я могу поделиться своим репозиторием на github, если вы сможете пройти через это, имея всего два файла с логикой.

sagg1295 19.05.2021 21:01

@ sagg1295 способ определения языка схемы GraphQL в ответе также использует graphql-subscriptions с graphql-ws, что то же самое.

Hongbo Miao 19.05.2021 21:11

но когда я искал в Google, чтобы делать подписки в graphql, я также обнаружил, что graphql-подписки — это отдельная вещь, чем graphql-ws. Может я ошибаюсь. Я думал, что это разные подходы к выполнению подписка в graphql.

sagg1295 19.05.2021 21:20

@sagg1295 графql-ws находится на том же уровне, что и подписки-транспорт-ws. А graphql-подписки - вещь другого уровня.

Hongbo Miao 19.05.2021 21:28

как обрабатывать переменные в запросе на подписку graphql, переданном клиентом на сервер, можете ли вы привести какой-либо пример? пытался просмотреть документацию, но не смог пройти через это

sagg1295 22.05.2021 22:20

В вашем первом примере есть import WebSocket from 'ws';, но затем вы делаете ws.Server, что правильно?

justin.m.chase 19.10.2021 16:37

Другие вопросы по теме