node.js - 在 GraphQL 参考实现中,resolvers 期望返回一个 Iterable,如何返回一个异步 Iterable?
问题描述
我Sequelize
用来访问我的关系数据库并在GraphQL解析器中提供结果。Sequelize
框架内的查询是异步执行的( bluebird)。为了缓冲大型结果集并避免在请求数百万条记录时对服务器的高内存需求,我想在我的解析器中返回一个迭代器。考虑这个简化的要点:
// root resolver
function allPersons(...) {
[...]
return {
nextId: 1,
maxId: 10000000,
[Symbol.iterator]: () => { return this },
next: function() {
let nextRes = { done: true, value: null }
if (this.nextId <= this.maxId) {
nextRes.value = sequelize.models.person.findById(this.currId)
nextRes.done = false
this.nextId = this.nextId + 1
}
return nextRes
}
}
上述工作,因为 Sequelize 构造的 Promise 返回为next()
's value
。当 this value-Promise 被解析时,它会从底层关系数据库中获取一条记录。因此,我同步构造了异步数据获取。这只有效,因为每个单独的提取都独立于所有其他提取。特别是不需要单次提取await
ed,在执行下一个之前。但是,逐行获取关系数据库在技术上效率低下,实际上是一种反模式。因此,我想实现一个缓冲区,它可以获取 10k 行的批次,为它们提供服务,直到批次为空,然后再获取下一个。但是,由于随后引入了异步事件的依赖关系,为了实现这一点,需要一个异步 Iterator ( Symbol.asyncIterator
)。
我需要做什么才能使GraphQL's reference implementation
(graphql-js 和/或 express-graphql)接受异步迭代器?请注意,我想避免使用Apollo GraphQL。
或者 Object-Stream 会是一个可能的解决方案吗?
帮助将不胜感激。
解决方案
半个解决方案:使用流并将它们转换为同步迭代器
因为 GraphQL 解析器预计会返回同步迭代器,所以流可用于将它们的数据提供给这样的迭代器。考虑问题中发布的原始示例的以下解决方案。请注意,流行的 ORM Sequelize不支持流,因此knex
这里使用了另一个节点包。
// Setup:
const knex = require('knex')
var dbCon = knex({
client: 'pg',
connection: {} // Define host, user, password, db (see knex docu)
})
// Get records as stream
var peopleStream = dbCon.select('*').from('people').stream()
// Serve stream within an synchronous iterator
var iter = {
[Symbol.iterator]: () => {
return this
},
next: function() {
let v = peopleStream.read() || null
console.log(JSON.stringify(v)) // Check, if it works.
return {
done: v === null,
value: v
}
}
}
然而,这确实只是解决方案的一半,因为只有数据源才能以所示的方式使用来生成流——这反过来又可以很容易地转换为同步迭代器,如此处所示。在我看来,GraphQL 的参考实现迫切需要支持异步迭代器作为解析器的结果值。有关更多详细信息,请参阅此功能请求。
推荐阅读
- c# - 如果文件中没有特定的字符串,我正在尝试报告一条消息。我不断收到相同的消息
- python - 如何连接两个用户定义类的集合
- command-line-interface - SSH 到 Pivotal 云铸造厂
- java - 如何从 SQL 查询中获取列名(Jooq,Java)
- php - 向 Laravel 工厂方法添加多个关系会导致 TypeError
- javascript - 如何使用javascript替换其他指定单词中的拉丁语指定单词?
- excel - 移动到下一个空行以从 Userform 填充单元格
- .net - 如何使用 Math.Net Numerics 计算正态分布的 Z 临界值?
- android - 如何在 c4droid 中使用 sd2 primitivies 和 sdl2_gfx
- ios - UIStackView 与 superview 的宽度成比例