Node.js从MongoDB取数用cursor返回响应时仅返首条且报ERR_HTTP_HEADERS_SENT错误
解决Express返回MongoDB多条记录时的ERR_HTTP_HEADERS_SENT错误
你遇到的这个问题其实很典型——HTTP响应的res.send()方法只能调用一次!
看你原来的代码,用cursor.each()遍历MongoDB的查询结果时,每拿到一条文档就调用res.send(doc),第一次调用就已经把响应发送给客户端了,此时HTTP连接的响应头部已经发送完毕,后续再调用res.send()自然就会触发Cannot remove headers after they are sent的错误,而且客户端只能收到第一条记录。
下面给你两种解决思路:
方案一:用toArray()一次性返回所有文档(推荐)
MongoDB的游标提供了toArray()方法,可以直接把所有查询结果转为数组,然后一次性发送给客户端,代码更简洁:
var router = express.Router(); var MongoClient = require('mongodb').MongoClient; var url = 'mongodb://localhost/EmployeeDB'; /* GET users listing. */ router.get('/', function(req, res, next) { MongoClient.connect(url, function(err, db) { // 先处理数据库连接错误 if (err) { return res.status(500).send('数据库连接失败'); } db.collection('Employee').find().toArray(function(err, docs) { // 处理查询错误 if (err) { db.close(); return res.status(500).send('查询员工数据失败'); } // 一次性返回所有员工记录 res.send(docs); db.close(); }); }); }); module.exports = router;
方案二:手动遍历收集所有文档后再发送
如果你一定要用each()遍历,可以先把所有文档收集到数组里,等遍历完成后再调用res.send():
var router = express.Router(); var MongoClient = require('mongodb').MongoClient; var url = 'mongodb://localhost/EmployeeDB'; /* GET users listing. */ router.get('/', function(req, res, next) { MongoClient.connect(url, function(err, db) { if (err) { return res.status(500).send('数据库连接失败'); } var cursor = db.collection('Employee').find(); var employees = []; cursor.each(function(err, doc) { if (err) { db.close(); return res.status(500).send('遍历员工数据失败'); } if (doc !== null) { // 把当前文档加入数组 employees.push(doc); } else { // doc为null时表示遍历完成,返回所有数据 res.send(employees); db.close(); } }); }); }); module.exports = router;
额外提醒
- 一定要记得处理各种错误场景(连接失败、查询失败),不然遇到问题时客户端会一直处于等待状态,你的程序也可能悄悄崩溃。
- 优先用
toArray(),它是驱动内置的便捷方法,代码更清晰,也不容易出错。
内容的提问来源于stack exchange,提问作者CoderTn
相关产品推荐
相关产品推荐

