我正在开展一个非常复杂的项目,其中必须处理许多mongoDB查询才能显示数据。现在,当对大量数据执行查询时,并不是所有数据都会在页面加载后立即显示。现在我在使用next()
函数之前通过设置超时函数来修复该问题。
所以这就是调用其中一个函数的地方:
router.get('/playwall', account.checkSession, playwalls.get, function(req, res, next) {
res.render('dashboard/playwalls/index');
});
检查用户是否已登录后,playwalls.get
功能将触发。这就是该功能现在的工作方式:
const playwalls = {
/* GET ALL PLAYWALLS FOR THAT USER, FOR ADMIN GET THEM ALL
-------------------------------------------------------------- */
get(req, res, next) {
req.session.playwalls = [];
const dataCollection = db.collection('data');
const data = dataCollection.find({});
console.log(typeof data)
const today = new Date();
data.forEach(function(d) {
console.log(data.length)
if(d.admin == req.session.userData.username || req.session.userData.role == 'admin') {
const expireDate = new Date(d.date);
if(expireDate < today && d.status == 'actief') {
playwalls.editStatus(d, req, res, next);
}
req.session.playwalls.push(d);
}
})
setTimeout(function() {
next();
}, 1000)
},
// Here the rest of the methods
}
我的问题是;如果next()
循环已处理查询返回的所有文档,我怎样才能确保仅data.forEach
函数被触发?所以我可以摆脱setTimeout()
函数。
希望我的问题很明确,有人可以帮助我。我在互联网上环顾四周,但无法找到合适的答案。
提前致谢!
答案 0 :(得分:2)
您应该使用Cursor.toArray,这样您就可以同步方式迭代文档,如果您需要在forEach
回调中执行某项异步作业,则可以使用Promise
&#39 ; S
const playwalls = {
/* GET ALL PLAYWALLS FOR THAT USER, FOR ADMIN GET THEM ALL
-------------------------------------------------------------- */
get(req, res, next) {
req.session.playwalls = [];
const dataCollection = db.collection('data');
const data = dataCollection.find({});
console.log(typeof data)
const today = new Date();
data.toArray(function (err, documents) {
if (err) {
return next(err);
}
documents.forEach(function (d) {
console.log(data.length)
if (d.admin == req.session.userData.username || req.session.userData.role == 'admin') {
const expireDate = new Date(d.date);
if (expireDate < today && d.status == 'actief') {
playwalls.editStatus(d, req, res, next);
}
req.session.playwalls.push(d);
}
})
next();
})
}, // Here the rest of the methods
}
答案 1 :(得分:1)
如何定义返回promise
的函数。
所以,将forEach
拉出一个单独的函数:
function promisedForEach(data) {
return new Promise(resolve => {
// your code
resolve('ready')
}
}
然后调用函数代替forEach:
promisedForEach(data).then( /* carry on */ )
答案 2 :(得分:0)
我认为setTimeout不会起作用,因为一切都必须在同一个线程中发生。因此,setTimeout只会在轮到执行时冻结。
另一种方法是使用rxjs观察者。 https://github.com/ReactiveX/RxJS当您想要在呈现页面之前等待应用程序的其他部分(例如中间件)中的内容时,这可能很有用。
您可以执行以下操作。我没有测试过这个。我会给你一些想法;
global.Rx = require('rxjs/Rx');
router.get('/playwall', function(req, res) {
const myProcesses = {
ready: new Rx.Subject(false),
loading: false,
readiness: {
process1: {
ready: false
},
process2: {
ready: false
},
process3: {
ready: false
}
},
checkReadiness: function (){
if (
this.readiness.process1==true
&& this.readiness.process2==true
&& this.readiness.process3==true
) {
this.loading = false;
this.ready.next(true);
}
},
};
//asynchronous process
(function (){
anObject.fetchAll().then(function (results){
myProcesses.readiness.process1 = true;
myProcesses.checkReadiness();
})
})();
//another asynchronous process
(function (){
anObject2.fetchAll().then(function (results){
myProcesses.readiness.process2 = true;
myProcesses.checkReadiness();
})
})();
//another asynchronous process
(function (){
anObject2.fetchAll().then(function (results){
myProcesses.readiness.process3 = true;
myProcesses.checkReadiness();
})
})();
//When all asynchronous processes have been completed
myProcesses.ready.subscribe({next: (v) => {
if (v==true){
res.render('ejs/products/checkout', {});
}
}});
});