刚开始学习Express,在线提供内容。页面取决于我能够管理的单个查询。但我坚持使用页面,我必须建立一个分页表。在这里,我必须首先调用2个查询以获得总计数,然后调用第二个数据集的第1页(限制20)。我正在使用Bootstrap表,它通过ajax调用在页面加载后呈现数据。响应应采用以下格式 -
{"total":100,"rows":[{"id":"59af010d93f3cc9ab0e09b3a","email":"test@test.com"},
{"id":"59af010d93f3cc9ab0e09b3a","email":"test2@test.com"}]}}
我有一个路由文件 - users.js,我在调用我的模型 - users.js
const User = require('../models/user');
router.get('/userslist', (req, res) => {
User.getUserList(req, (err, user,next) => {
if(err) throw err;
if(!user){
return res.json({success: false, msg: 'User not found'});
}
res.json({"rows":user});
});
});
module.exports = router;
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
module.exports.getUserList = function(req, callback){
skip = parseInt(req.query.offset);
nPerPage = parseInt(req.query.limit);
sortby = req.query.sort;
orderby = req.query.order;
User.find().exec(function (err, count){
User.find(callback).sort([[sortby, orderby]]).skip(skip > 0 ? (skip+1) : 0).limit(nPerPage).exec(function(err, data){
res.json( {"total":count.length,"rows":data} );
});
})
在这个模型文件中,我试图一起调用2个查询,这就是抛出错误。但是当我只调用没有res.json的第二个查询时,它就可以工作。
请告诉我调用多个查询的最佳做法是什么,以及如何提高我对回调的理解。我觉得那是我完全空白的地方。如果您可以通过简单的示例推荐任何在线内容,我将不胜感激。
答案 0 :(得分:0)
这不是发出回调的正确方法。而你的重大问题是res
不在范围内。但是还有其他一些你应该注意的事情。
而是将结果(数据和/或错误)传递给调用函数并在那里解析:
const User = require('../models/user');
router.get('/userslist', (req, res, next) => {
User.getUserList(req, (err, data) => {
if(err) next(err);
if(!data){
return res.json({success: false, msg: 'User not found'});
}
res.json(data);
});
});
module.exports = router;
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
module.exports.getUserList = function(req, callback) {
skip = parseInt(req.query.offset);
nPerPage = parseInt(req.query.limit);
sortby = req.query.sort;
orderby = req.query.order;
User.count().exec((err, count) => {
User.find().sort([[sortby, orderby]])
.skip(skip > 0 ? (skip+1) : 0).limit(nPerPage)
.exec((err, data) => {
callback(err,{"total":count,"rows":data});
});
})
}
或者更好的是,学会使用承诺:
const User = require('../models/user');
router.get('/userslist', (req, res, next) => {
User.getUserList(req).then(data => {
if(!data) {
return res.json({success: false, msg: 'User not found'});
}
res.json(data);
}).catch(next);
});
module.exports = router;
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
module.exports.getUserList = function(req) {
skip = parseInt(req.query.offset);
nPerPage = parseInt(req.query.limit);
sortby = req.query.sort;
orderby = req.query.order;
return User.count().then(count =>
User.find().sort([[sortby, orderby]])
.skip(skip > 0 ? (skip+1) : 0)
.limit(nPerPage).then(data => ({"total":count,"rows":data}))
);
}
甚至使用async/await
进行现代化,并使计数和数据请求与Promise.all()
并行
const User = require('../models/user');
router.get('/userslist', async (req, res, next) => {
try {
let data = await User.getUserList(req)
if(!data) {
return res.json({success: false, msg: 'User not found'});
}
res.json(data);
} catch(e) {
next(e);
}
});
module.exports = router;
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
module.exports.getUserList = (req) => {
skip = parseInt(req.query.offset);
nPerPage = parseInt(req.query.limit);
sortby = req.query.sort;
orderby = req.query.order;
return Promise.all([
User.count().then(count => ({ total: count })),
User.find().sort([[sortby, orderby]])
.skip(skip > 0 ? (skip+1) : 0)
.limit(nPerPage)
.then( data => ({ rows: data }))
]).then(result => result.reduce((acc,curr) =>
Object.assign(acc,curr),{})
);
}
在任何一种情况下,通过控制器返回数据都不是模型函数的任务。而是将数据传回,让控制器上的方法实际执行输出。
另请注意,使用
.count()
优先于.find()
,然后获取结果数组的长度。前者效率更高,因为它从"光标"得到结果计数。而实际上并不需要迭代并返回光标中的所有文档,这就是后者正在做的事情。