GraphQL.js использует iterall
под капотом.Для поддержки асинхронных итераций базовый код должен будет использовать метод forAwaitEach
из этой библиотеки вместо метода forEach
, который используется сейчас.Это может быть возможно, но я не уверен, что это не нарушит другие функции.
Если все, что вы хотите сделать, это извлечь все people
в некоторых кусках произвольного размера, вам не нужночтобы сделать что-то особенно необычное:
async function getAllPeople () {
const chunkSize = 10000
const startId = 1
const endId = await sequelize.models.person.max('id')
const people = []
let lower = startId
let upper = startId + chunkSize
while (upper < (endId + 1)) {
const chunk = await sequelize.models.person.findAll({
where: {
id: {
[Op.and]: {
[Op.gte]: lower,
[Op.lt]: upper,
}
}
},
})
people.push(chunk)
lower = lower + chunkSize
upper = upper + chunkSize
}
return people
}
РЕДАКТИРОВАТЬ: Чтобы обойти проблему с памятью, вам придется эффективно разбить полезную нагрузку на несколько ответов и иметь возможность вернуть их обратно.вместе на стороне клиента.В дорожной карте Аполлона есть директива @stream
, которая делает именно это, и я думаю, что некоторые люди экспериментировали с ней, но я думаю, что может пройти некоторое время, прежде чем мы увидим зрелую реализацию этого.@defer
имеет аналогичный механизм и в настоящее время поддерживается Apollo, но работает на уровне разрешения, поэтому в данном случае это не очень поможет.
Вы можете взломать его, используя подписки , которые случайно используют асинхронные итераторы.Возможно, вам по-прежнему потребуется инициировать отправку данных с использованием запроса или мутации, но затем вы можете отправить их клиенту по подписке.
Я думаю, к сожалению, самое простое решение с учетом нынешнего инструментария - просто реализовать разбиение на страницы назапрос и клиентский кусок вместе общий результат.