Variabel Global di app.js dapat diakses di rute?

91

Bagaimana cara menetapkan variabel app.jsdan membuatnya tersedia di semua rute, setidaknya di index.jsfile yang terletak di rute. menggunakan kerangka kerja ekspres dannode.js

Technupe
sumber
1
The app.locals objek memiliki sifat yang variabel lokal dalam aplikasi. Di file rute Anda, referensikan dengan req.app.locals.
Ronnie Royston

Jawaban:

65

Untuk membuat variabel global, cukup deklarasikan tanpa varkata kunci. (Secara umum, ini bukan praktik terbaik, tetapi dalam beberapa kasus dapat berguna - berhati-hatilah karena akan membuat variabel tersedia di mana saja.)

Berikut adalah contoh dari visionmedia / screenshot-app

file app.js :

/**
 * Module dependencies.
 */

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

app = express();

//... require() route files

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

//...
Jesse Fulton
sumber
6
Sebagai catatan, biasanya lebih baik bersikap eksplisit tentang meneruskan variabel dan membuat instance-nya, jadi Anda tidak secara tidak sengaja membatalkan referensi di tempat lain dalam aplikasi, atau apa pun yang Anda miliki.
Paul
3
Ini benar-benar bentuk yang buruk, seperti yang dicatat oleh Paul. Saya menyarankan pola injeksi yang disebutkan di bawah ini. Ya, lebih banyak kode pelat ketel sehingga tidak terlihat "cantik" tetapi memastikan kode Anda modular ... sesuatu yang akan Anda sukai jika ini bukan proyek terakhir Anda;)
srquinn
Itu tergantung dari keadaan IMHO. Ya, global vars umumnya bukan praktik yang baik (seperti yang saya nyatakan dalam jawaban saya) dan ketika memulai dari awal, saya akan mengatakan mengatur semuanya ke dalam modul terpisah. Tetapi jika Anda mengintegrasikan dengan kode yang ada, seringkali ada pertimbangan lain - ini kebetulan merupakan satu solusi (mudah, namun berbahaya).
Jesse Fulton
2
Bisakah seseorang menjelaskan mengapa ini berfungsi dengan mengacu pada semantik Javascript? Cakupan mana yang appterkait?
Ali
Saya tidak berpikir jawaban ini harus ditandai sebagai correctsatu.
Code Cooker
93

Sebenarnya sangat mudah untuk melakukan ini dengan menggunakan metode "set" dan "get" yang tersedia pada objek ekspres.

Contoh sebagai berikut, katakanlah Anda memiliki variabel bernama config dengan hal-hal yang terkait dengan konfigurasi yang ingin Anda sediakan di tempat lain:

Di app.js:

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

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

Di routes / index.js

exports.index = function(req, res){
  var config = req.app.get('config');
  // config is now available
  ...
}
Mandy
sumber
Setel 'app' global? Iya. Tetapi metode ini paling baik untuk menyelamatkan kita dari masalah dan kekacauan.
diproart
53
untuk pendatang yang terlambat: app.configure dihapus dalam express 4.x
zamil
Bagus, req.app.get('name')berfungsi seperti pesona. Properti ini menyimpan referensi ke contoh aplikasi Express yang menggunakan middleware. expressjs.com/pt-br/api.html#req.app
Lazaro Fernandes Lima Suleiman
58

Cara yang rapi untuk melakukannya adalah dengan menggunakan yang app.localsdisediakan oleh Express itu sendiri. Berikut dokumentasinya.

// 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;
}
Ali
sumber
1
Saya menggunakan metode ini untuk menemukan layanan http dan dengan mudah menimpa dalam pengujian unit.
Alex
28

Untuk mendeklarasikan variabel global, Anda perlu menggunakan objek global . Seperti global.yourVariableName. Tapi itu bukanlah cara yang benar. Untuk berbagi variabel antar modul coba gunakan gaya injeksi seperti

someModule.js:

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

app.js

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

Atau Anda dapat menggunakan objek pengganti untuk melakukan itu. Seperti hub .

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');
Vadim Baryshev
sumber
7

Berikut penjelasannya dengan baik, singkatnya:

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

Jadi Anda bekerja dengan satu set modul Node, mungkin kerangka kerja seperti Express.js, dan tiba-tiba merasa perlu untuk membuat beberapa variabel global. Bagaimana Anda membuat variabel global di Node.js?

Saran paling umum untuk yang satu ini adalah "mendeklarasikan variabel tanpa kata kunci var" atau "menambahkan variabel ke objek global" atau "menambahkan variabel ke objek GLOBAL". Yang mana yang Anda gunakan?

Pertama, mari kita analisis objek global. Buka terminal, mulai Node REPL (prompt).

> 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'
Victor Cruz
sumber
Di Express - saat menggunakan jshint atau linting, secara umum - ini menjadi masalah.
Steven Ventimiglia
6

cara termudah adalah dengan mendeklarasikan variabel global di app.js Anda, sejak awal:

global.mySpecialVariable = "something"

lalu di rute mana pun Anda bisa mendapatkannya:

console.log(mySpecialVariable)
Dukun
sumber
1
Di Express - saat menggunakan jshint atau linting, secara umum - ini menjadi masalah.
Steven Ventimiglia
5

Ini adalah pertanyaan yang membantu, tetapi bisa lebih dari itu dengan memberikan contoh kode yang sebenarnya. Bahkan artikel terkait tidak benar-benar menunjukkan implementasi. Oleh karena itu, saya dengan rendah hati menyampaikan:

Di app.jsfile Anda , bagian atas file:

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 tidak akan memiliki referensi apa pun ke app.get()metode. Biarkan ini ditentukan di file rute individu.

routes/index.js:

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

dan akhirnya, sebuah rute file yang sebenarnya, 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
John Gordon
sumber
4

Cara yang saya sukai adalah menggunakan dependensi melingkar *, yang didukung node

  • di app.js tentukan var app = module.exports = express();sebagai urutan pertama bisnis Anda
  • Sekarang modul apa pun yang diperlukan setelah fakta dapat var app = require('./app')mengaksesnya


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


rute / indeks.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');
Will Stern
sumber
Tip yang bagus. Saya baru saja berpindah dari metode Requirement ('./ myroutes') (app) ke melakukan ini dan kepala saya terbentur dinding selama 10 menit mencoba mencari tahu mengapa tidak ada rute saya yang berhasil. Jangan lupa untuk mengambil spesifikasi rute di myroutes.js dari blok fungsi. Doh!
greg
2

Seperti yang telah dibagikan orang lain, app.set('config', config)bagus untuk ini. Saya hanya ingin menambahkan sesuatu yang tidak saya lihat dalam jawaban yang ada yang cukup penting. Instance Node.js dibagikan ke semua permintaan, jadi meskipun mungkin sangat praktis untuk membagikan beberapa configatau routerobjek secara global, menyimpan data runtime secara global akan tersedia di seluruh permintaan dan pengguna . Pertimbangkan contoh yang sangat sederhana ini:

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

Jika Anda mengunjungi /bardan permintaan lain mencapai /foo, pesan Anda akan menjadi "Selamat datang di foo!". Ini adalah contoh yang konyol, tetapi maksudnya jelas.

Ada beberapa poin menarik tentang ini di Mengapa sesi node.js yang berbeda berbagi variabel? .

Charlie Schliesser
sumber
1

Saya memecahkan masalah yang sama, tetapi saya harus menulis lebih banyak kode. Saya membuat server.jsfile, yang menggunakan express untuk mendaftarkan rute. Ini memperlihatkan sebuah fungsi,, registeryang dapat digunakan oleh modul lain untuk mendaftarkan rute mereka sendiri. Ini juga mengekspos fungsi startServer,, untuk mulai mendengarkan sebuah port

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
}

Di modul lain, gunakan file ini untuk membuat rute.

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
}

Di file utama, bootstrap keduanya.

app.js

require('./server').startServer(7000)
require('./web/help').registerHelp()
Amar Dev
sumber
1

ini adalah hal yang cukup mudah, tetapi jawaban orang-orang membingungkan dan rumit pada saat yang bersamaan.

izinkan saya menunjukkan kepada Anda bagaimana Anda dapat mengatur variabel global di expressaplikasi Anda . Jadi Anda dapat mengaksesnya dari rute mana pun sesuai kebutuhan.

Katakanlah Anda ingin menyetel variabel global dari /rute utama Anda

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

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

Jadi Anda akan mendapatkan req.app dari semua rute. dan kemudian Anda harus menggunakan localsuntuk menyetel data global. seperti di atas menunjukkan Anda sudah siap. sekarang saya akan menunjukkan cara menggunakan data itu

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

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

Seperti di atas dari registerrute Anda mengakses data yang telah diatur sebelumnya.

Ini adalah bagaimana Anda bisa membuat benda ini bekerja!

Code Cooker
sumber
0

Jawaban John Gordon adalah yang pertama dari lusinan jawaban setengah dijelaskan / terdokumentasi yang saya coba, dari banyak, banyak situs, yang benar-benar berfungsi. Terima kasih, Tuan Gordon. Maaf, saya tidak punya poin untuk menandai jawaban Anda.

Saya ingin menambahkan, untuk pemula lainnya untuk node-route-file-splitting, bahwa penggunaan fungsi anonim untuk 'index' adalah yang akan lebih sering dilihat, jadi dengan menggunakan contoh John untuk main.js, fungsi- kode yang setara yang biasanya ditemukan adalah:

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

Saya menggunakan app.all

Metode app.all () berguna untuk memetakan logika "global" untuk prefiks jalur tertentu atau kecocokan arbitrer.

Dalam kasus saya, saya menggunakan confit untuk manajemen konfigurasi,

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

Di rute, Anda cukup melakukannya req.app.get('config').get('cookie');

nilesh
sumber