#node.js #graphql #apollo-server
#node.js #graphql #apollo-сервер
Вопрос:
Я сканирую карту сайта сайта с помощью apollo server. но когда я отправляю запрос с playground, он выдает результаты, не дожидаясь завершения функции. Как я могу приостановить сканирование для получения результата? И как я могу мгновенно отобразить отсканированный массив URL-адресов сайта на стороне клиента?
Если я использую подписку graphql, мне нужно сохранять данные один за другим. это было бы много данных.
Примечание: система работает, и данные сохраняются в mongoose.
scanSitemap: async (parent, { id, data }, { WebLink }) => {
let dataset = [];
const generator = await SitemapGenerator('https://example.org', {
stripQuerystring: false,
filepath: null
});
generator.start();
generator.on('add', (url) => {
dataset.push(url);
console.log(dataset);
});
generator.on('done', () => {
return new WebLink({
status: 1, domain: 'test', websiteId: id, urls: dataset
}).save();
});
},
Ответ №1:
В этом случае ваш scanSitemap
распознаватель должен возвращать a Promise
, который разрешается только при 'done'
отправке события из SitemapGenerator
Почему? Ну, согласно документам ApolloServer:
Распознаватели часто выполняют асинхронные действия, такие как выборка из базы данных или внутреннего API. Для поддержки этого распознаватель может возвращать обещание, которое преобразуется в любой другой поддерживаемый возвращаемый тип. (https://www.apollographql.com/docs/apollo-server/data/resolvers/#return-values )
В этом случае ваш распознаватель определенно выполняет асинхронную операцию — очистку карты сайта — так что это хорошая ситуация для использования Promises.
Возвращая a Promise
, вы даете указание серверу Apollo дождаться, пока будут доступны результаты вашей асинхронной операции. Согласно вашему коду, я полагаю, вы хотите решить эту проблему в конце дня:
new WebLink({
status: 1, domain: 'test', websiteId: id, urls: dataset
}).save()
Я переписал ваш код для использования Promises (я также протестировал его на своей стороне, и он работает!)
scanSitemap: async (parent, { id, data }, { WebLink }) => {
// Returning a new promise inside of the GraphQL resolver
// that accepts a callback with a resolve argument that we'll use later
return new Promise((resolve) => {
let dataset = [];
// No need to await SitemapGenerator
const generator = SitemapGenerator('https://example.org', {
filepath: null,
stripQuerystring: false,
});
generator.start();
generator.on('add', (url) => {
dataset.push(url);
console.log(dataset);
});
generator.on('done', () => {
// Resolving the promise
// and telling ApolloServer that our GraphQL resolver result is ready
resolve(
new WebLink({
domain: 'test',
status: 1,
urls: dataset,
websiteId: id,
}).save(),
);
});
});
};
Вот отличный ресурс об обещаниях, если вы заинтересованы в дальнейшем:
https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke