node.js - 节点中间件在继续之前等待功能完成
问题描述
我在 Node 中导出此函数,但我需要在Booking.find
其余代码继续之前完成该函数。
原来的:
module.exports = function() {
return function secured(req, res, next) {
if (req.user) {
const mongoose = require('mongoose');
const Booking = mongoose.model('Booking');
Booking.find((err, docs) => { // I need this to run first
bookingsCount = docs.length;
});
const userProfile = req.user;
res.locals = {
count: bookingsCount, // so that when the page loads this var is available
userProfile: JSON.stringify(userProfile, null, 2),
name: userProfile.displayName,
loggedInEmail: userProfile.emails[0].value,
isAuthenticated: req.isAuthenticated(),
};
return next();
}
req.session.returnTo = req.originalUrl;
res.redirect('/login');
};
};
我尝试使用回调创建单独的函数,但我认为这不正确,因为那将是一种异步方法,但我相信我需要使这部分同步。
然后我在下面尝试了这个如何等待猫鼬搜索异步等待的返回,它似乎每次都正确返回。
更新:
module.exports = function () {
return async function secured(req, res, next) { // added async
if (req.user) {
const mongoose = require('mongoose');
const Booking = mongoose.model('Booking');
await Booking.find((err, docs) => { // added await
bookingsCount = docs.length;
});
const userProfile = req.user;
res.locals = {
count: bookingsCount,
userProfile: JSON.stringify(userProfile, null, 2),
name: userProfile.displayName,
loggedInEmail: userProfile.emails[0].value,
isAuthenticated: req.isAuthenticated(),
};
return next();
}
req.session.returnTo = req.originalUrl;
res.redirect('/login');
};
};
在这种情况下以及在每个页面请求的中间件中正确使用 await 是否正确,我可以安全地假设页面在Booking.find
承诺解决之前不会加载?
按照建议尝试1:
module.exports = function () {
return async function secured(req, res, next) {
if (req.user) {
let docs;
try {
docs = await Booking.find((err, docs) => {
const bookingsCount = docs.length;
const userProfile = req.user;
res.locals = {
count: bookingsCount,
userProfile: JSON.stringify(userProfile, null, 2),
name: userProfile.displayName,
loggedInEmail: userProfile.emails[0].value,
isAuthenticated: req.isAuthenticated(),
};
});
return next();
} catch (err) {
console.log(err);
return next(err);
}
}
req.session.returnTo = req.originalUrl;
res.redirect('/login');
};
};
按要求预订型号:
const mongoose = require('mongoose');
const bookingSchema = new mongoose.Schema({
firstName: {
type: String,
required: 'This field is required',
},
lastName: {
type: String,
required: 'This field is required',
},
tourType: {
type: String,
required: 'This field is required',
},
dateBooked: {
type: String,
required: 'This field is required',
},
tourDate: {
type: String,
required: 'This field is required',
},
pax: {
type: String,
required: 'This field is required',
},
phone: {
type: String,
required: 'This field is required',
},
customerEmail: {
type: String,
required: 'This field is required',
},
pickupAddress: {
type: String,
required: 'This field is required',
},
operatorName: {
type: String,
required: 'This field is required',
},
paidStatus: {
type: String,
required: 'This field is required',
},
notes: {
type: String,
},
guidesName: {
type: String,
},
guidesEmail: {
type: String,
},
bookingCreatedSent: {
type: Boolean,
},
calendarEventCreated: {
type: Boolean,
},
clientReminderSent: {
type: Boolean,
},
remindOperators: {
type: Boolean,
},
remindGoCapeGuides: {
type: Boolean,
},
feedbackSent: {
type: Boolean,
},
});
// Custom validation for email
bookingSchema.path('customerEmail').validate((val) => {
emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return emailRegex.test(val);
}, 'Invalid e-mail.');
mongoose.model('Booking', bookingSchema);
DB.js - 模型依赖
const mongoose = require('mongoose');
require('dotenv').config();
env = process.env.NODE_ENV;
envString = env;
// mongoDB connection string
const url = process.env['MONGO_DB_URL' + envString];
console.log(url);
mongoose.connect(url, {useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false})
.then(() => {
console.log('connected!', process.env.PORT || '8000');
})
.catch((err) => console.log(err));
//db.close();
require('./booking.model');
可用的尝试:
module.exports = function() {
return async function secured(req, res, next) {
if (req.user) {
const Booking = require('../model/booking.model');
let docs;
try {
docs = await Booking.find((err, docs) => {
const bookingsCount = docs.length;
const userProfile = req.user;
res.locals = {
count: bookingsCount,
userProfile: JSON.stringify(userProfile, null, 2),
name: userProfile.displayName,
loggedInEmail: userProfile.emails[0].value,
isAuthenticated: req.isAuthenticated(),
};
});
return next();
} catch (err) {
console.log(err);
return next(err);
}
}
req.session.returnTo = req.originalUrl;
res.redirect('/login');
};
};
解决方案
在您更新的代码中,您都在尝试使用等待和回调。
同样要在 await 中捕获错误,我们需要使用 try catch 块。
所以你可以像这样重写你的函数:
const mongoose = require("mongoose");
const Booking = mongoose.model("Booking");
module.exports = function() {
return async function secured(req, res, next) {
if (req.user) {
let docs;
try {
docs = await Booking.find();
const bookingsCount = docs.length;
const userProfile = req.user;
res.locals = {
count: bookingsCount,
userProfile: JSON.stringify(userProfile, null, 2),
name: userProfile.displayName,
loggedInEmail: userProfile.emails[0].value,
isAuthenticated: req.isAuthenticated()
};
return next();
} catch (err) {
console.log(err);
return next(err);
}
}
req.session.returnTo = req.originalUrl;
res.redirect("/login");
};
};
并且要解决原代码中的问题,需要像这样将里面的 res.locals 相关代码移到 Find 回调中,这样只有在 Find 工作后才能工作。
module.exports = function() {
return function secured(req, res, next) {
if (req.user) {
const mongoose = require("mongoose");
const Booking = mongoose.model("Booking");
Booking.find((err, docs) => {
bookingsCount = docs.length;
const userProfile = req.user;
res.locals = {
count: bookingsCount,
userProfile: JSON.stringify(userProfile, null, 2),
name: userProfile.displayName,
loggedInEmail: userProfile.emails[0].value,
isAuthenticated: req.isAuthenticated()
};
return next();
});
next();
}
req.session.returnTo = req.originalUrl;
res.redirect("/login");
};
};
更新:
您需要在这样的架构代码之后在预订中导出您的模型:
module.exports = mongoose.model('Booking', bookingSchema);
并在您的函数中像这样导入它:
const Booking = require("../models/booking"); //TODO: update your path
而不是这一行:
const Booking = mongoose.model("Booking");
推荐阅读
- git - 带有模板的“hg log”的Git等效项?
- javascript - 使用 foreach 循环的短 URL 数组以及如何使用 nodejs TALL 解析每个 url
- php - Symfony 3 从数据库自动加载数据
- python - 如何在 python 测试中传递命令行参数
- docker - 尝试在 unix:///var/run/docker.sock 连接到 Docker 守护程序套接字时获得权限被拒绝:
- javascript - 修改自动检测用户名和密码以在 Chrome 上保存密码建议
- java - 如何检测声明的exe在java中是否可见
- r - dplyr `left_join()` 不适用于作为 LHS 变量的字符对象
- ampl - 在ampl 中定义距离矩阵的函数。不断收到“我未定义”
- twitter-bootstrap - Bootstrap 年历 - 工作示例