CNode

[mysql] query.stream 将查询结果流写入response如何handle中途可能产生的error?

问答
Zzenggo发布于10 年前最后回复10 年前4 回复4990 浏览0 收藏

有时会碰到向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)

H
hyj1991#1·10 年前

这里是不是你理解有一点偏差 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协议

L
luoyjx#2·10 年前

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

query.pipe(res);

end事件时,

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

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

Z
zenggo#4·10 年前
引用 luoyjx既然使用的stream,那你就不需要等数据完全接收完了再发送,直接 end事件时, 不然数据量大了之后,说不定就会 boom !

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

参与回复
登录后即可参与回复。登录