本文针对 Node.js 环境下使用 Mongoose 进行数据库循环查询时,因异步操作导致最终获取的数据数组为空的问题,提供了一种基于 Node.js 原生 events 模块的解决方案。通过 EventEmitter 的事件监听与触发机制,确保所有异步查询完成后才返回结果,从而正确处理嵌套异步操作。
Node.js Mongoose 异步查询问题背景
在 Node.js 环境中操作 Mongoose 时,若尝试通过嵌套方式查询并将数据循环推入数组,最终得到的数组往往为空。经过多次搜索未能找到有效方案,后经专家指导得知,这是由 Mongoose 及 Node.js 的异步机制导致的。查阅相关资料后,找到一种较为简便的处理方法,如下所示。
原始代码问题分析
//原来的代码
var shoppingModel = global.dbHandle.getModel('shopping');
var cartsshop = [];
for(var i = 0;i<carts.length;i++){
shoppingModel.findOne({title:carts[i].title},function (err,shops) {
if(err){
return next(err);
}else{
cartsshop.push(shops);
}
});
}
console.log(cartsshop);//[]
利用 EventEmitter 解决异步问题
该方法通过引入 Node.js 自身提供的 events 模块来实现。
events 模块
Node.js 中所有异步 I/O 操作在完成时,都会向事件队列发送一个事件。
Node.js 中的许多对象都会分发事件:例如 net.Server 对象在每次有新连接时会分发事件,fs.readStream 对象在文件打开时会发出事件。所有这些产生事件的对象均为 events.EventEmitter 的实例。
EventEmitter 类
events 模块仅提供一个对象:events.EventEmitter。EventEmitter 的核心功能是对事件触发与事件监听器进行封装。可通过 require("events"); 来访问该模块。
以下是一个基础实例,
EventEmitter 基础示例
//event.js 文件
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter();
event.on('some_event', function() {
console.log('some_event 事件触发');
});
setTimeout(function() {
event.emit('some_event');
}, 1000);
将原有代码改进如下:
改进后的 Mongoose 查询实现
var shoppingModel = global.dbHandle.getModel('shopping');
var cartsshop = [];
var obj ;
var j = 0;
var myEventEmitter = new events.EventEmitter();
myEventEmitter.on('next',addResult);
function addResult() {
cartsshop.push(obj);
j++;
if(j==carts.length){
console.log(cartsshop);
res.json(cartsshop);
}
}
for(var i = 0;i<carts.length;i++){
var ii = i;
shoppingModel.findOne({title:carts[ii].title},function (err,shops) {
if(err){
return next(err);
}else{
obj = shops;
myEventEmitter.emit('next');
}
});
}
当然,在使用前必须引入相关模块。
var events = require('events');
最后,成功将数据取出并返回给客户端。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。