MongoDB7升级后Mongoose中_.bind回调报错的解决问询
解决MongoDB 7升级后Mongoose回调兼容问题
升级MongoDB 7后,Mongoose移除了对query.exec()回调参数的支持,原代码中_.bind(query.exec, query)触发"no longer accepts a callback function"异常。尝试改用Promise链式调用时,因未正确传递查询结果给sendData导致逻辑失效。
原错误代码
return _.bind(function(req, res, next) { var query = this.getQuery(req); async.waterfall([ _.bind(query.exec, query), ], this.sendData(req, res, next)); }, this);
原sendData函数
sendData: function(req, res, next) { var fields = _parseJSON(req.query.fields, []), optFields; if (!_.isArray(fields)) { fields = [fields]; } function _sendData(err, data) { if (err) { res.json({'data':data,'error':err}); } else { res.json(data); } } fields = _.intersection(fields, this.model.optionalFields); return function(err, data) { if (fields.length > 0) { var isArray = _.isArray(data); async.map(isArray ? data : [data], function(doc, callback) { var obj = doc.toObject(); async.each(fields, function(field, cb) { doc['get' + field].call(doc, function(err, value) { obj[field] = value; cb(err); }); }, function(err) { callback(err, obj); }); }, function(err, objs) { return _sendData(err, isArray ? objs : objs[0]); }); } else { _sendData(err, data); } };
解决方案
sendData返回的是一个接收(err, data)参数的回调函数,因此需要将query.exec()返回的Promise结果适配到该格式,同时确保this上下文正确:
方式1:Promise链式调用
return _.bind(function(req, res, next) { var query = this.getQuery(req); query.exec() // 查询成功时,传入null(无错误)和结果给sendData的回调 .then(result => this.sendData(req, res, next)(null, result)) // 查询失败时,传入错误和null给回调 .catch(err => this.sendData(req, res, next)(err, null)); }, this);
方式2:async/await(更易读)
return _.bind(async function(req, res, next) { var query = this.getQuery(req); try { const result = await query.exec(); this.sendData(req, res, next)(null, result); } catch (err) { this.sendData(req, res, next)(err, null); } }, this);
关键说明
之前的改写失效原因是仅调用了this.sendData(req, res, next),但未将查询结果作为参数传递给它返回的回调函数。sendData本身是一个工厂函数,返回的才是真正处理数据的逻辑函数,必须传入err和data参数才能触发后续的字段处理和响应发送逻辑。
内容的提问来源于stack exchange,提问作者peter
相关产品推荐
相关产品推荐

