[mysql] query.stream 将查询结果流写入response如何handle中途可能产生的error?
发布于 7 年前 作者 zenggo 4062 次浏览 来自 问答

有时会碰到向db查询大量记录,需要边接收边处理的场景。mysql模块提供了一个流式查询的方法streaming query rows。 如果需要每收到一条记录就写入到http response中,如何处理接收过程中可能产生的错误呢?此时response head已经发出200,且已经正常发送了部分数据,当query发生错误时,如何通知客户端发生了错误? 代码如下:

const pool = require('mysql').createPool(...);
const http = require('http');

http.createServer((req, res)=> {
	response.statusCode = 200;
	let sql = 'SELECT * FROM tb1';
	let query = pool.query(sql);
	query
		.on('result', (row)=> {
			res.write(JSON.stringify(row));
		})
		.on('error', (err)=> {
			res.end(); // 如何handle中途可能产生的error?
		})
		.on('end', ()=> {
			res.end();
		});
}).listen(8000);
4 回复

这里是不是你理解有一点偏差 write只会向缓冲区写数据,此时并不会发送给客户端,只有当你调用res.end()方法时,才会把缓冲区的数据发送给客户端,所以这里你完全可以写成类似这样的:

const pool = require('mysql').createPool(...);
const http = require('http');

http.createServer((req, res)=> {
	let sql = 'SELECT * FROM tb1';
	let query = pool.query(sql);
	let dataArr = [];
	query
    	.on('result', (row)=> {
        	dataArr = dataArr.concat(row);
    	})
    	.on('error', (err)=> {
        	err = err instanceof Error && err || new Error(err);
        	res.statusCode = 500;
        	res.end(err.message);
    	})
    	.on('end', ()=> {
        	res.statusCode = 200;
        	res.end(JSON.stringify(dataArr));
    	});
}).listen(8000);

http协议一个请求只能对应一次响应,这是由协议本身决定的,如果你想多次发送数据给客户端,可以用websocket或者索性是TCP协议

既然使用的stream,那你就不需要等数据完全接收完了再发送,直接

query.pipe(res);

end事件时,

.on('end', ()=> {
  res.end();
});

不然数据量大了之后,说不定就会 boom !

@hyj1991 原来如此,谢谢解答!

@luoyjx 谢谢解答,我就是为了解决查询数据量大时的发送问题,现已改用了pipe

回到顶部