Подписка не подключается с помощью ApolloServer

Я пытаюсь создать подписку и запустить ее с ApolloServer (v 2.2.2). У меня была установка, которая внезапно перестала работать. Когда я пытаюсь подключиться к подписке в graphiql / Playground, я получаю сообщение об ошибке:

{
  "error": "Could not connect to websocket endpoint ws://localhost:4000/graphql. Please check if the endpoint url is correct."
}

Поскольку в моем приложении есть конечные точки отдыха, мне нужно иметь экспресс, но я не могу получить минимальный пример из нижеприведенного:

import http from 'http';
import { ApolloServer, PubSub } from 'apollo-server-express';
import express from 'express';

const pubsub = new PubSub();

// The DB
const messages = [];

const typeDefs = `
type Query {
  messages: [String!]!
}
type Mutation {
  addMessage(message: String!): [String!]!
}
type Subscription {
  newMessage: String!
}

schema {
  query: Query
  mutation: Mutation
  subscription: Subscription
}
`;

const resolvers = {
  Query: {
    messages() {
      return messages;
    }
  },
  Mutation: {
    addMessage(root, { message }) {
      let entry = JSON.stringify({ id: messages.length, message: message });
      messages.push(entry);
      pubsub.publish('newMessage', { entry: entry });
      return messages;
    },
  },
  Subscription: {
    newMessage: {
      resolve: (message) => {
        return message.entry;
      },
      subscribe: () => pubsub.asyncIterator('newMessage'),
    },
  },
};

const app = express();

const PORT = 4000;

const server = new ApolloServer({
  typeDefs,
  resolvers,
  subscriptions: {
    onConnect: () => console.info('Connected to websocket'),
  }
});

server.applyMiddleware({ app })

const httpServer = http.createServer(app);
server.installSubscriptionHandlers(httpServer);

httpServer.listen(PORT, () => {
  console.info(`? Server ready at http://localhost:${PORT}${server.graphqlPath}`)
  console.info(`? Subscriptions ready at ws://localhost:${PORT}${server.subscriptionsPath}`)
})

Другие конечные точки работают нормально, но не может создать WebSocket. Насколько я понимаю, мне не нужно использовать другой сервер или порт (см. https://www.ably.io/concepts/websockets). Я повозился с SubsciptionServer, но этим должен заниматься installSubscriptionHandlers (вот код).

Поведение ключевого слова "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) для оценки ваших знаний,...
11
0
9 045
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Оказывается, у Firefox есть проблемы с веб-сокетами (см. этот отчет об ошибке, который снова появился даже после предполагаемого исправления).

В Firefox он работает сразу после запуска нового браузера, но после некоторой горячей перезагрузки перестает работать. Следующее помогает начать все заново, но не решает проблему с перезагрузкой:

const wsLink = new WebSocketLink({
  uri: SUBSCRIPTION_URI,
  options: {
    reconnect: true,
    timeout: 20000,
    lazy: true,
  },
});

window.addEventListener('beforeunload', () => {
  // @ts-ignore - the function is private in typescript
  wsLink.subscriptionClient.close();
});

Я думаю, что ошибка связана с этим SO-вопросом: «веб-сокет был прерван во время загрузки страницы» в Firefox для Socket.io

Если вы хотите протестировать различные решения, я создал пример репозитория: https://github.com/gforge/subscription_example, который работает как сам по себе, так и с контейнером Docker.

Прошло много времени, и теперь я столкнулся с той же проблемой и нашел решение.

import { createServer } from 'http';
const app = express();
const server = new ApolloServer({});
server.applyMiddleware({ app });
const httpServer = createServer(app);
server.installSubscriptionHandlers(httpServer);
server.listen()

Работает на меня

В последней строке вместо server.listen() пришлось сделать httpServer.listen(). Может, это опечатка автора ответа?

Tyler Collier 05.10.2021 23:49

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