首页 > 解决方案 > 节点中间件在继续之前等待功能完成

问题描述

我在 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');
    };
    };       

标签: node.jsmongooseasync-await

解决方案


在您更新的代码中,您都在尝试使用等待和回调。

同样要在 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");

推荐阅读