I am exporting this function in Node but I need the Booking.find
function to complete before the rest of the code continues.
Original:
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');
};
};
I tried to create separate functions with a callback but I don't think that worked correct because that would then be an asynchronous approach but I believe I need to make this part synchronous.
Then I tried this below How to wait for the return of a Mongoose search async await and it seems to be returning correctly each time.
Updated:
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');
};
};
Is this correct usage of await in such a case and in middelware for each page request and can I safely assume that the page wont load until the Booking.find
promise is resolved?
Attempt 1 as suggested:
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');
};
};
Booking model as requested:
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 - model is dependent
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');
Use-able attempt:
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');
};
};