【发布时间】:2019-10-25 03:56:54
【问题描述】:
我正在尝试从BigQuery 读取查询并将其流式传输到前端。在带有 Express 的 Node.js-land 中,这将是:
app.get('/endpoint', (req, res) => {
bigQuery.createQueryStream(query).pipe(res);
});
但是,createQueryStream() 确实不创建 Node.js 流,而是返回 表行 的自定义流对象,因此它失败了:
(node:21236) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: 第一个参数必须是字符串或缓冲区类型之一。接收到的类型对象
这在official documentation中得到了证实:
bigquery.createQueryStream(query)
.on('data', function(row) {
// row is a result from your query.
})
那么,有没有办法将 BigQuery 数据流式传输到前端?我想到了两种可能的解决方案,但想知道是否有人知道更好的方法:
-
JSON.stringify()行并返回JSONL而不是普通的JSON。这增加了解码它的前端负担,但在双方都相当容易。 - 移至REST API 并使用request 进行实际流式传输,例如:
request(url, { body: { query, params } }).pipe(res)(或任何特定的API,还没有在那里挖掘)。
我很困惑,一个说它可以流式传输的 Node.js 库不适用于 Node.js 原生流,但情况似乎是这样。
【问题讨论】:
-
你找到解决办法了吗?
-
亲切!我们最终手动构建了一个 JSON,然后以一种非常老套的方式“流式传输”每一行。但是我们试图流式传输大量数据,而 BigQuery 仍然很慢。我们在某个时候(出于其他原因!)转向了 Python,并希望那里的库会更成熟,但不,它实际上差很多。
-
@tjbandes 这就是我们最终要做的:stackoverflow.com/a/64746763/12271991
-
我明白了,感谢您的更新!似乎将结果与
[,]连接起来有点违背了流媒体的目的,对吧?我想您正在服务器端节省内存,但客户端仍然需要等待整个数组才能JSON.parse。 -
是的,完全同意。我什至不确定我们是否在服务器端节省内存,但我们可能会。另一个小优点是数据以块的形式发送,因此与等待和一次性发送数据相比在最后一个块到达服务器后(较低的后端前端带宽需要)。
标签: javascript node.js express stream google-bigquery