Проблема определения области с использованием require() в узле JS

#node.js #express #scope #requirejs #require

#node.js #выразить #область #requirejs #требовать

Вопрос:

Я настроил веб-сервер, используя node JS и модуль Express. Мой код выглядит следующим образом :

дерево файлов:

 /src
 |
  -- server.js
  -- /app
     |
      -- routes.js
  

server.js

 // set up ======================================================================
var express  = require('express');
var app      = express();
var mongoose = require('mongoose');
  

 // configuration ===============================================================
mongoose.connect(configDB.url);
  

 // routes ======================================================================
require('./app/routes.js')(app, passport);

// launch ======================================================================
app.listen(port);
  

routes.js

     module.exports = function(app, passport) {
        app.get('/some-route', function(req, res) {
            // this line bugs out
            var User = mongoose.model('User', userSchema);
        });
    };
  

Мой вопрос:

Вызов mongoose.model() в маршрутах.js выдает следующую ошибку

Ошибка ссылки: mongoose не определен

Почему mongoose не известен в этом контексте, когда я включил его в server.js , файл, в котором routes.js включается ли в него? Должен ли я require() mongoose снова в routes.js ? Чего мне здесь не хватает?

Ответ №1:

Переменные, определенные в модуле, являются локальными только для этого модуля. Они не входят в область действия других модулей, которые вы require() используете с этим модулем. Вот почему mongoose я не знаю вашего модуля routes. require() Операция не вставляет код прямо в вызывающий модуль. Вместо этого он загружает этот код с диска, а затем вставляет его в свою собственную функцию и вызывает эту функцию. Это дает каждому загруженному модулю свою собственную независимую область видимости. Он не вставлен в текущую область.

В подобных случаях у вас есть несколько вариантов:

  1. Require() в модуле mongoose снова в маршрутах. Обычно это предпочтительнее, когда это возможно, потому что это делает модуль routes более самодостаточным и его легче повторно использовать по мере необходимости в тех вещах, которые ему нужны.

  2. Передайте объект, которым вы хотите поделиться с конструктором маршрутов, точно так же, как вы передаете в app и passport . Этот метод предпочтительнее, когда элемент, необходимый другому модулю, является не просто результатом простой загрузки модуля. Например, app это результат вызова функции конструктора, поэтому единственный способ для другого модуля использовать тот же app экземпляр — передать его вам.

  3. У вас могут быть маршруты, вызывающие какой-либо другой модуль для запроса информации. Например, поскольку вы уже передали app объект в routes, вы можете поместить mongoose объект либо как свойство app объекта, чтобы на него можно было ссылаться таким образом, либо вы можете добавить метод к app объекту для его извлечения с помощью вызова метода.

В этом случае, поскольку mongoose это просто кэшированный модуль, вероятно, имеет смысл просто require() ввести его снова, но любой из трех описанных выше методов будет работать.

Комментарии:

1. Итак, если я правильно понимаю; В случае номер один модуль mongoose будет кэшироваться и не вызовет дополнительной нагрузки?

2. @matthiasdv — Да, узел кэширует все модули, поэтому запрос во второй раз просто возвращает дескриптор кэшированного модуля. Он не загружает и не запускает новый код.

Ответ №2:

Модули, которые включены в файл, не видны в другом файле. Здесь вы можете найти список глобальных объектов, доступных в каждом создаваемом вами модуле:

https://nodejs.org/api/globals.html

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

В вашем случае вам нужно require('mongoose') указать файлы, которые вам нужны, и он построен таким образом, чтобы поддерживать существующее соединение с базой данных.