Глобальна змінна в app.js, доступна в маршрутах?


91

Як мені встановити змінну в, app.jsі вона буде доступна на всіх маршрутах, принаймні у index.jsфайлі, який знаходиться в маршрутах. використовуючи експрес-фреймворк іnode.js


1
Об'єкт app.locals має властивості, які є локальними змінними в додатку. У файлі маршруту посилайтеся на нього req.app.locals.
Ронні Ройстон,

Відповіді:


65

Щоб створити глобальну змінну, просто оголосіть її без varключового слова. (Загалом кажучи, це не найкраща практика, але в деяких випадках вона може бути корисною - будьте обережні, оскільки це зробить змінну доступною скрізь.)

Ось приклад із visionmedia / screenshot-app

файл app.js :

/**
 * Module dependencies.
 */

var express = require('express')
  , stylus = require('stylus')
  , redis = require('redis')
  , http = require('http');

app = express();

//... require() route files

файл routes / main.js

//we can now access 'app' without redeclaring it or passing it in...

/*
 * GET home page.
 */

app.get('/', function(req, res, next){
  res.render('index');
});

//...

6
Як примітка, як правило, краще бути явним щодо передавання змінних навколо та створення їх екземплярів, щоб ви випадково не зануляли посилання десь ще в додатку або що у вас є.
Павло,

3
Це справді погана форма, як зазначив Пол. Я б запропонував схему введення, згадану нижче. Так, більше кодової таблички, щоб він не виглядав "гарним", але він гарантує, що ваш код модульний ... щось, що сподобається, якщо це не ваш останній проект;)
srquinn

Це залежить від обставин ІМХО. Так, глобальні вари, як правило, не є гарною практикою (як я вже зазначив у своїй відповіді), і, починаючи з нуля, я б сказав, що все це організовується в окремі модулі. Але якщо ви інтегруєтесь із наявним кодом, часто є й інші міркування - це просто одне (легке, але небезпечне) рішення.
Джессі Фултон,

2
Хтось може пояснити, чому це працює, посилаючись на семантику Javascript? З якою сферою appасоціюється?
Алі

Я не думаю, що цю відповідь слід позначити як correctодну.
Code Cooker

91

Насправді це дуже легко зробити за допомогою методів "set" та "get", доступних для експрес-об'єкта.

Приклад, наведений нижче, скажімо, у вас є змінна, що називається config, з вашими матеріалами, пов'язаними з конфігурацією, які ви хочете бути доступними в інших місцях:

У app.js:

var config = require('./config');

app.configure(function() {
  ...
  app.set('config', config); 
  ...
}

У маршрутах / index.js

exports.index = function(req, res){
  var config = req.app.get('config');
  // config is now available
  ...
}

Встановити глобальний додаток? Так. Але цей метод найкраще врятує нас від проблем і хаосу.
diproart

53
для тих, хто запізнюється: app.configure видалено в express 4.x
zamil

Приємно, req.app.get('name')працює як шарм. Ця властивість містить посилання на екземпляр програми Express, яка використовує проміжне програмне забезпечення. expressjs.com/pt-br/api.html#req.app
Лазаро Фернандес Ліма Сулейман

57

Акуратний спосіб зробити це - використовувати, app.localsнаданий самим Express. Ось документація.

// In app.js:
app.locals.variable_you_need = 42;

// In index.js
exports.route = function(req, res){
    var variable_i_needed = req.app.locals.variable_you_need;
}

1
Я використав цей метод, щоб знайти служби http і легко замінити їх в модульних тестах.
Алекс

28

Щоб оголосити глобальну змінну, потрібно використовувати глобальний об'єкт. Як global.yourVariableName. Але це не вірно. Для обміну змінними між модулями спробуйте використовувати стиль введення типу

someModule.js:

module.exports = function(injectedVariable) {
    return {
        somePublicMethod: function() {
        },
        anotherPublicMethod: function() {
        },
    };
};

app.js

var someModule = require('./someModule')(someSharedVariable);

Або ви можете використовувати для цього сурогатний об’єкт. Як хаб .

someModule.js:

var hub = require('hub');

module.somePublicMethod = function() {
    // We can use hub.db here
};

module.anotherPublicMethod = function() {
};

app.js

var hub = require('hub');
hub.db = dbConnection;
var someModule = require('./someModule');

7

Ось поясніть добре, коротше:

http://www.hacksparrow.com/global-variables-in-node-js.html

Отже, ви працюєте з набором модулів Node, можливо, фреймворком, як Express.js, і раптом відчуваєте необхідність зробити деякі змінні глобальними. Як зробити глобальні змінні в Node.js?

Найпоширеніша порада для цього - або "оголосити змінну без ключового слова var", або "додати змінну до глобального об'єкта", або "додати змінну до об'єкта GLOBAL". Який з них ти використовуєш?

Для початку давайте проаналізуємо глобальний об’єкт. Відкрийте термінал, запустіть вузол REPL (підказка).

> global.name
undefined
> global.name = 'El Capitan'
> global.name
'El Capitan'
> GLOBAL.name
'El Capitan'
> delete global.name
true
> GLOBAL.name
undefined
> name = 'El Capitan'
'El Capitan'
> global.name
'El Capitan'
> GLOBAL.name
'El Capitan'
> var name = 'Sparrow'
undefined
> global.name
'Sparrow'

У Express - при використанні jshint або підключення, загалом - це стає проблемою.
Стівен Вентімілья

6

найпростіший спосіб - оголосити глобальну змінну у своєму app.js на самому початку:

global.mySpecialVariable = "something"

тоді на будь-яких маршрутах ви можете його отримати:

console.log(mySpecialVariable)

1
У Express - при використанні jshint або підключення, загалом - це стає проблемою.
Стівен Вентімілья

5

Це було корисне запитання, але могло бути і більше, якщо навести фактичні приклади коду. Навіть пов'язана стаття насправді не показує реалізації. Тому я смиренно заявляю:

У вашому app.jsфайлі, у верхній частині файлу:

var express = require('express')
, http = require('http')
, path = require('path');

app = express(); //IMPORTANT!  define the global app variable prior to requiring routes!

var routes = require('./routes');

app.js не матиме жодного посилання на app.get()метод. Залиште їх визначати в окремих файлах маршрутів.

routes/index.js:

require('./main');
require('./users');

і нарешті, власне файл маршрутів routes/main.js:

function index (request, response) {
    response.render('index', { title: 'Express' });
}

app.get('/',index); // <-- define the routes here now, thanks to the global app variable

4

Моїм кращим способом є використання циклічних залежностей *, які підтримує вузол

  • в app.js визначте var app = module.exports = express();як своє перше замовлення бізнесу
  • Тепер будь-який модуль, необхідний після факту, може var app = require('./app')отримати до нього доступ


app.js

var express   = require('express');
var app = module.exports = express(); //now app.js can be required to bring app into any file

//some app/middleware, config, setup, etc, including app.use(app.router)

require('./routes'); //module.exports must be defined before this line


routes / index.js

var app = require('./app');

app.get('/', function(req, res, next) {
  res.render('index');
});

//require in some other route files...each of which requires app independently
require('./user');
require('./blog');

Чудова порада. Я просто перейшов від методу require ('./ myroutes') (app) до цього і вдарився головою об стіну протягом 10 хвилин, намагаючись зрозуміти, чому жоден з моїх маршрутів не працює. Не забудьте вилучити специфікації маршруту в myroutes.js з функціонального блоку. Дох!
greg

2

Як вже поділились інші, app.set('config', config)чудово для цього. Я просто хотів додати те, чого я не бачив у існуючих відповідях, що є досить важливим. Екземпляр Node.js ділиться між усіма запитами, тому, хоча може бути дуже практичним ділитися деякими об'єктами configабо routerоб'єктами в глобальному масштабі, глобальне зберігання даних виконання буде доступним для запитів та користувачів . Розглянемо цей дуже простий приклад:

var express = require('express');
var app = express();

app.get('/foo', function(req, res) {
    app.set('message', "Welcome to foo!");
    res.send(app.get('message'));
});

app.get('/bar', function(req, res) {
    app.set('message', "Welcome to bar!");

    // some long running async function
    var foo = function() {
        res.send(app.get('message'));
    };
    setTimeout(foo, 1000);
});

app.listen(3000);

Якщо ви завітаєте на сторінку /barта отримаєте інший запит /foo, ваше повідомлення буде "Ласкаво просимо до foo!". Це безглуздий приклад, але він усвідомлює суть справи.

Є кілька цікавих моментів з цього приводу, чому різні сеанси node.js діляться змінними? .


1

Я вирішив ту ж проблему, але мені довелося написати більше коду. Я створив server.jsфайл, який використовує Express для реєстрації маршрутів. Він надає функцію, registerяка може використовуватися іншими модулями для реєстрації власних маршрутів. Він також надає функцію,, startServerщоб почати слухати порт

server.js

const express = require('express');
const app = express();

const register = (path,method,callback) => methodCalled(path, method, callback)

const methodCalled = (path, method, cb) => {
  switch (method) {
    case 'get':
      app.get(path, (req, res) => cb(req, res))
      break;
    ...
    ...  
    default:
      console.log("there has been an error");
  }
}

const startServer = (port) => app.listen(port, () => {console.log(`successfully started at ${port}`)})

module.exports = {
  register,
  startServer
}

В іншому модулі використовуйте цей файл для створення маршруту.

help.js

const app = require('../server');

const registerHelp = () => {
  app.register('/help','get',(req, res) => {
    res.send("This is the help section")
  }),
  app.register('/help','post',(req, res) => {
    res.send("This is the help section")
  })}

module.exports = {
  registerHelp
}

У головному файлі завантажте обидва файли.

app.js

require('./server').startServer(7000)
require('./web/help').registerHelp()

0

Відповідь Джона Гордона була першою з десятків напів пояснених / задокументованих відповідей, які я спробував із багатьох сайтів, які насправді працювали. Дякую, пане Гордон. Вибачте, у мене немає балів, щоб підтвердити вашу відповідь.

Я хотів би додати, для інших початківців для розбиття вузлів-маршрутів-файлів, що використання анонімної функції для 'index' частіше бачитиме, тому, використовуючи приклад Джона для main.js, функціонально- еквівалентний код, який зазвичай можна знайти, це:

app.get('/',(req, res) {
    res.render('index', { title: 'Express' });
});

0

Я використовував app.all

Метод app.all () корисний для відображення “глобальної” логіки для певних префіксів шляху або довільних збігів.

У моєму випадку я використовую confit для управління конфігурацією,

app.all('*', function (req, res, next) {
    confit(basedir).create(function (err, config) {
        if (err) {
            throw new Error('Failed to load configuration ', err);
        }
        app.set('config', config);
        next();
    });
});

У маршрутах ви просто робите req.app.get('config').get('cookie');


0

це досить легко, але відповіді людей заплутані та одночасно складні.

дозвольте мені показати вам, як ви можете встановити глобальну змінну у своєму expressдодатку. Таким чином, ви можете отримати доступ до нього з будь-якого маршруту за потреби.

Скажімо, ви хочете встановити глобальну змінну з вашого основного /маршруту

router.get('/', (req, res, next) => {

  req.app.locals.somethingNew = "Hi setting new global var";
});

Тож ви отримаєте req.app з усіх маршрутів. і тоді вам доведеться використовувати, localsщоб встановити глобальні дані в. як показано вище, все готово. зараз я покажу вам, як використовувати ці дані

router.get('/register', (req, res, next) => {

  console.log(req.app.locals.somethingNew);
});

Як і вище з registerмаршруту, до якого ви отримуєте доступ до даних, було встановлено раніше.

Ось як можна змусити цю штуку працювати!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.