使用 Express 将 BigQuery 流式传输到前端

我正在尝试从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]: 第一个参数必须是字符串或缓冲区类型之一。接收类型对象


这在官方文档中得到证实:


bigquery.createQueryStream(query)

  .on('data', function(row) {

    // row is a result from your query.

  })

那么,有没有办法将 BigQuery 数据流式传输到前端?我想过两种可能的解决方案,但想知道是否有人知道更好的方法:


JSON.stringify()行并返回JSONL而不是普通JSON。这增加了解码它的前端负担,但使双方都相当容易。

转到REST API并使用以下请求进行实际流式传输:(request(url, { body: { query, params } }).pipe(res)或任何特定的 API,尚未在那里挖掘)。

我很困惑,一个 Node.js 库说它可以进行流式处理,但它不适用于 Node.js 本机流,但情况似乎确实如此。


桃花长相依
浏览 242回答 2
2回答

白衣非少年

BigQuery 旨在与为不同编程语言编写的各种不同客户端库一起使用,因此,它不返回特定于 nodejs 的数据结构,而是返回大多数结构化编程语言通用的更通用的结构,例如作为对象。回答您的问题,是的,有一种方法可以将 BigQuery 数据流式传输到前端,但这是一个相当个人的选择,因为它所需要的只是从一种数据类型转换为另一种数据类型。但是,我想说最直接的方法是调用JSON.stringify(),您已经提到过。

跃然一笑

我们最终制作了一个实现,将 BigQuery 的回复拼接到一个大的 JSON 数组中:exports.stream = (query, params, res) => {&nbsp; // Light testing for descriptive errors in the parameters&nbsp; for (let key in params) {&nbsp; &nbsp; if (typeof params[key] === "number" && isNaN(params[key])) {&nbsp; &nbsp; &nbsp; throw new TypeError(`The parameter "${key}" should be a number`);&nbsp; &nbsp; }&nbsp; }&nbsp; return new Promise((resolve, reject) => {&nbsp; &nbsp; let prev = false;&nbsp; &nbsp; const onData = row => {&nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; // Only handle it when there's a row&nbsp; &nbsp; &nbsp; &nbsp; if (!row) return;&nbsp; &nbsp; &nbsp; &nbsp; // There was a previous row written before, so add a comma&nbsp; &nbsp; &nbsp; &nbsp; if (prev) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; res.write(",");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; res.write(stringify(row));&nbsp; &nbsp; &nbsp; &nbsp; prev = true;&nbsp; &nbsp; &nbsp; } catch (error) {&nbsp; &nbsp; &nbsp; &nbsp; console.error("Cannot parse row:", error);&nbsp; &nbsp; &nbsp; &nbsp; // Just ignore it, don't write this frame&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; };&nbsp; &nbsp; const onEnd = () => {&nbsp; &nbsp; &nbsp; res.write("]");&nbsp; &nbsp; &nbsp; res.end();&nbsp; &nbsp; &nbsp; resolve();&nbsp; &nbsp; };&nbsp; &nbsp; res.writeHead(200, { "Content-Type": "application/json" });&nbsp; &nbsp; res.write("[");&nbsp; &nbsp; bigQuery&nbsp; &nbsp; &nbsp; .createQueryStream({ query, params })&nbsp; &nbsp; &nbsp; .on("error", reject)&nbsp; &nbsp; &nbsp; .on("data", onData)&nbsp; &nbsp; &nbsp; .on("end", onEnd);&nbsp; });};它将通过拼接来构建一个大型 JSON 数组:[&nbsp; &nbsp;// <- First character sentstringify(row1)&nbsp; &nbsp;// <- First row,&nbsp; &nbsp;// <- add comma on second row iterationstringify(row2)&nbsp; &nbsp;// <- Second row...stringify(rowN)&nbsp; &nbsp;// <- Last row]&nbsp; &nbsp;// <- Send the "]" character to close the array这有以下优点:数据在可用时立即发送,因此带宽需求较低。(取决于 BigQuery 实现)服务器端的内存需求较低,因为并非所有数据都一次保存在内存中,只有小块。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript