Node.js使用Highland对接MongoDB>=4.0查询流时无限输出undefined问题
问题原因
- 该问题和你使用的MongoDB服务端镜像版本(mongo:4.2.10)无关,故障出在npm包
mongodb4.x版本的接口破坏性变更与Highland流的适配逻辑上。 mongodb4.0.0及以上版本中,collection.find()返回的Cursor对象不再默认实现Node.js标准Readable流接口,也不兼容旧版同步迭代协议。Highland接收到不符合流/可迭代协议的对象时,会将其当作普通值反复推送,最终导致无限输出undefined、堆内存耗尽。- 额外注意:原代码存在变量名笔误,定义的客户端实例名为
client,查询时误用了mongoClient;同时4.x版本驱动要求必须显式调用connect()建立连接,不支持旧版的隐式连接逻辑。
修复方案
二选一即可,优先选方案1,改动最小。
方案1:显式转换为标准Node.js流(最小改动)
4.x版本的Cursor提供了stream()方法,调用后返回标准Readable流,可直接被Highland正常消费,修改后代码如下:
const connectionString = ... const client = new MongoClient(connectionString); await client.connect(); // 4.x驱动必须显式建立连接 const records = client .db('mydb') .collection('acollection') .find({}) .stream(); // 关键:显式获取可读流实例 const res = await hi(records).tap(_log).collect().toPromise(Promise); function _log(record) { console.log(record); return record; }
方案2:基于异步迭代器手动构造Highland流
如果不想使用Node.js原生流,也可以利用4.x Cursor原生支持的AsyncIterable协议,手动构造Highland流:
const connectionString = ... const client = new MongoClient(connectionString); await client.connect(); const cursor = client .db('mydb') .collection('acollection') .find({}); // 遍历异步迭代器向Highland推送数据 const records = hi(async (push, next) => { for await (const doc of cursor) { push(null, doc); } push(null, hi.nil); // 遍历完成后推送结束标记 }); const res = await records.tap(_log).collect().toPromise(Promise); function _log(record) { console.log(record); return record; }
内容的提问来源于stack exchange,提问作者Dotan
相关产品推荐
相关产品推荐

