Промежуточное программное обеспечение узла ожидает завершения функции, прежде чем продолжить - PullRequest
0 голосов
/ 10 января 2020

Я экспортирую эту функцию в 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');
    };
    };

Я пытался создать отдельные функции с обратным вызовом, но я не думаю, что это сработало правильно, потому что тогда это был бы асинхронный подход, но я считаю, что мне нужно сделать эта часть синхронна.

Тогда я попробовал это ниже Как ждать возврата Mon goose search asyn c, ожидают, и кажется будет возвращаться правильно каждый раз .

Обновлено:

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

1 Ответ

1 голос
/ 10 января 2020

В вашем обновленном коде вы оба пытаетесь использовать await и callback.

Также, чтобы отлавливать ошибки в 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");
  };
};

UPDATE :

Вам необходимо экспортировать свою модель при бронировании после кода схемы следующим образом:

module.exports = mongoose.model('Booking', bookingSchema);

И импортировать ее следующим образом в своей функции:

const Booking = require("../models/booking"); //TODO: update your path

Вместо этой строки:

const Booking = mongoose.model("Booking");
...