Я пытаюсь создать подписку и запустить ее с 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 (вот код).



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Оказывается, у 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(). Может, это опечатка автора ответа?