如何在 Node.js 中为自定义 EventEmitter 正确实现暂停/恢复
我正在构建一个报告服务,其中一个进程提交查询,检索令牌,然后将令牌交给另一个进程,我们从中查询报告服务并将结果流式传输回来。
给定这段代码,我应该如何实现阻塞调用,直到暂停为假?
var util = require('util')
, events = require('events')
, pg = require('pg')
// QueryHandler is an EventEmitter
function QueryHandler(sql) {
this.paused = true
pg.connect(connectionString, function(err, client) {
// error handling ignored for sake of illustration
var query = client.query(sql)
query.on('row', function(row) {
if (this.paused) {
// Somehow block until paused === false
}
this.emit(row)
}.bind(this))
}.bind(this))
}
util.inherits(QueryHandler, events.EventEmitter)
QueryHandler.prototype.resume = function() {
this.paused = false
}
这是一个交互图,解释了我想要实现的目标:
- Web 浏览器向前端 Web 服务器请求报告
- 前端 Web 服务器向报告服务请求与特定查询相关的令牌
- 同时,报告服务连接到 PostgreSQL并发送查询
- 前端 Web 服务器将报告服务的 URL 和令牌返回到 Web 浏览器
- Web 浏览器使用返回的令牌向报告服务发出 Ajax(长轮询)请求
- 报告服务在行返回到 Web 浏览器时将行流式传输Web 浏览器
由于一切都是异步的,因此步骤 3 可能会在 Web 浏览器连接之前开始返回数据,这意味着数据丢失。我可以将数据缓冲在内存中,直到客户端返回,但我宁愿阻止数据行的发送,因为这会阻止 RAM 使用。或者也许我只是在开玩笑,RAM 仍然会在底层库中使用?无论如何,指针赞赏!
I'm building a reporting service, where one process submits a query, retrieves a token, then hands off the token to another process, from which we query the reporting service and stream the results back.
Given this code, how should I implement the blocking call until paused is false?
var util = require('util')
, events = require('events')
, pg = require('pg')
// QueryHandler is an EventEmitter
function QueryHandler(sql) {
this.paused = true
pg.connect(connectionString, function(err, client) {
// error handling ignored for sake of illustration
var query = client.query(sql)
query.on('row', function(row) {
if (this.paused) {
// Somehow block until paused === false
}
this.emit(row)
}.bind(this))
}.bind(this))
}
util.inherits(QueryHandler, events.EventEmitter)
QueryHandler.prototype.resume = function() {
this.paused = false
}
Here's an interaction diagram explaining what I'm trying to achieve:
- The web browser asks the frontend webserver for a report
- The frontend webserver asks the reporting service for a token relating to a specific query
- Simultaneously, the reporting service connects to PostgreSQL and sends the query
- The frontend webserver returns the reporting service's URL and token back to the web browser
- The web browser does an Ajax (long polling) request to the reporting service with the returned token
- The reporting service streams rows as they come in back to the web browser
Because everything is asynchronous, step 3 might start returning data before the web browser connects, which would mean data loss. I could buffer the data in memory until the client comes back, but I'd rather block the emission of data rows, since that would prevent RAM use. Or maybe I'm just kidding myself and RAM will still be used in the underlying library? Anyway, pointers appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果你要阻塞事件循环,我认为你必须等待 web-workers api(线程,某种)被实现。
我认为保存来自 pg 的行是一个更好的主意。
If you're going to block in the event-loop I think you have to wait for the web-workers api (threads, sort of) to be implemented.
I think saving the rows coming from pg is a better idea.