Biến toàn cầu trong app.js có thể truy cập được trong các tuyến?


91

Làm cách nào để tôi đặt một biến trong đó app.jsvà làm cho nó có sẵn trong tất cả các tuyến, ít nhất là trong index.jstệp nằm trong các tuyến. sử dụng khung thể hiện vànode.js


1
Các app.locals đối tượng có thuộc tính là các biến cục bộ trong ứng dụng. Trong tệp tuyến đường của bạn, hãy tham chiếu nó với req.app.locals.
Ronnie Royston

Câu trả lời:


65

Để tạo một biến toàn cục, chỉ cần khai báo nó mà không cần vartừ khóa. (Nói chung đây không phải là phương pháp hay nhất, nhưng trong một số trường hợp, nó có thể hữu ích - chỉ cần cẩn thận vì nó sẽ làm cho biến có sẵn ở mọi nơi.)

Đây là một ví dụ từ ứng dụng visionmedia / screenshot

tệp app.js :

/**
 * Module dependencies.
 */

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

app = express();

//... require() route files

tệp tuyến đường / 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
Như một lưu ý, nói chung tốt hơn là nên rõ ràng về việc chuyển các biến xung quanh và khởi tạo chúng, vì vậy bạn không vô tình bỏ qua tham chiếu ở một nơi khác trong ứng dụng hoặc những gì có bạn.
Paul

3
Paul lưu ý rằng đây thực sự là một hình thức tồi tệ Tôi sẽ đề xuất mô hình tiêm được đề cập bên dưới. Vâng, nhiều nồi hơi mã tấm vì vậy nó không trông "đẹp" nhưng nó đảm bảo mã của bạn là mô-đun ... một cái gì đó bạn sẽ thích nếu đây không phải là dự án cuối cùng của bạn;)
srquinn

Nó phụ thuộc vào các trường hợp IMHO. Vâng, các vars toàn cầu nói chung không phải là một thực tiễn tốt (như tôi đã nêu trong câu trả lời của mình) và khi bắt đầu lại từ đầu, tôi muốn nói tổ chức mọi thứ thành các mô-đun riêng biệt. Nhưng nếu bạn đang tích hợp với mã hiện có, thường có những cân nhắc khác - đây chỉ là một giải pháp (dễ nhưng nguy hiểm).
Jesse Fulton

2
Ai đó có thể giải thích tại sao điều này hoạt động liên quan đến ngữ nghĩa của Javascript? Phạm vi nào appđược liên kết với?
Ali

Tôi không nghĩ câu trả lời này nên đánh dấu là correctmột.
Code Cooker

91

Nó thực sự rất dễ dàng để làm điều này bằng cách sử dụng các phương thức "set" và "get" có sẵn trên một đối tượng express.

Ví dụ như sau, giả sử bạn có một biến được gọi là config với nội dung liên quan đến cấu hình mà bạn muốn có ở những nơi khác:

Trong app.js:

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

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

Trong các tuyến đường / index.js

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

Đặt 'ứng dụng' toàn cầu? Đúng. Nhưng phương pháp này tốt nhất để cứu chúng ta khỏi các vấn đề và sự hỗn loạn.
diproart

53
dành cho những người đến muộn: app.configure bị xóa trong express 4.x
zamil

Tốt đẹp, req.app.get('name')hoạt động như một sự quyến rũ. Thuộc tính này giữ một tham chiếu đến phiên bản của ứng dụng Express đang sử dụng phần mềm trung gian. expressjs.com/pt-br/api.html#req.app
Lazaro Fernandes Lima Suleiman

57

Một cách đơn giản để làm điều này là sử dụng app.localsdo Express cung cấp. Đây là tài liệu.

// 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
Tôi đã sử dụng phương pháp này để định vị các dịch vụ http và dễ dàng ghi đè trong các bài kiểm tra đơn vị.
Alex

28

Để khai báo một biến toàn cục, bạn cần sử dụng đối tượng toàn cục . Giống như global.yourVariableName. Nhưng nó không phải là một cách đúng. Để chia sẻ các biến giữa các mô-đun, hãy thử sử dụng kiểu tiêm như

someModule.js:

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

app.js

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

Hoặc bạn có thể sử dụng đối tượng thay thế để làm điều đó. Giống như trung tâm .

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

Đây là giải thích ngắn gọn:

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

Vì vậy, bạn đang làm việc với một tập hợp các mô-đun Node, có thể là một khuôn khổ như Express.js, và đột nhiên cảm thấy cần phải tạo một số biến toàn cục. Làm cách nào để bạn tạo biến toàn cục trong Node.js?

Lời khuyên phổ biến nhất cho vấn đề này là "khai báo biến mà không có từ khóa var" hoặc "thêm biến vào đối tượng toàn cục" hoặc "thêm biến vào đối tượng GLOBAL". Bạn sử dụng cái nào?

Trước hết, hãy phân tích đối tượng toàn cục. Mở một thiết bị đầu cuối, bắt đầu Node REPL (dấu nhắc).

> 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'

Trong Express - khi sử dụng jshint hoặc linting, nói chung - điều này trở thành một vấn đề.
Steven Ventimiglia

6

cách dễ nhất là khai báo một biến toàn cục trong app.js của bạn, ngay từ đầu:

global.mySpecialVariable = "something"

sau đó trong bất kỳ tuyến đường nào bạn có thể nhận được nó:

console.log(mySpecialVariable)

1
Trong Express - khi sử dụng jshint hoặc linting, nói chung - điều này trở thành một vấn đề.
Steven Ventimiglia

5

Đây là một câu hỏi hữu ích, nhưng có thể hơn thế bằng cách đưa ra các ví dụ mã thực tế. Ngay cả bài viết được liên kết không thực sự hiển thị một triển khai. Do đó, tôi khiêm tốn phục tùng:

Trong app.jstệp của bạn , đầu tệp:

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 sẽ không có bất kỳ tham chiếu nào đến app.get()phương thức. Để chúng được xác định trong các tệp tuyến đường riêng lẻ.

routes/index.js:

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

và cuối cùng, một tuyến đường tập tin thực tế, 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

Cách ưa thích của tôi là sử dụng các phụ thuộc vòng tròn *, nút nào hỗ trợ

  • trong app.js xác định var app = module.exports = express();là đơn hàng kinh doanh đầu tiên của bạn
  • Bây giờ bất kỳ mô-đun nào được yêu cầu sau khi thực tế có thể var app = require('./app')truy cập


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


route / 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');

Mẹo hay. Tôi vừa chuyển từ phương thức request ('./ myroutes') (app) sang thực hiện điều này và đập đầu vào tường trong 10 phút để cố gắng tìm ra lý do tại sao không có tuyến đường nào của tôi hoạt động. Đừng quên lấy các đặc tả tuyến trong myroutes.js ra khỏi một khối chức năng. Doh!
greg

2

Như những người khác đã chia sẻ, app.set('config', config)thật tuyệt vời cho điều này. Tôi chỉ muốn thêm một cái gì đó mà tôi không thấy trong các câu trả lời hiện có khá quan trọng. Một cá thể Node.js được chia sẻ trên tất cả các yêu cầu, vì vậy mặc dù có thể rất thực tế khi chia sẻ một số confighoặc routerđối tượng trên toàn cầu, nhưng việc lưu trữ dữ liệu thời gian chạy trên toàn cầu sẽ có sẵn trên các yêu cầu và người dùng . Hãy xem xét ví dụ rất đơn giản này:

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

Nếu bạn truy cập /barvà một yêu cầu khác xuất hiện /foo, thông báo của bạn sẽ là "Chào mừng bạn đến với foo!". Đây là một ví dụ ngớ ngẩn, nhưng nó sẽ giải quyết được vấn đề.

Có một số điểm thú vị về điều này tại Tại sao các phiên node.js khác nhau chia sẻ các biến? .


1

Tôi đã giải quyết vấn đề tương tự, nhưng tôi phải viết nhiều mã hơn. Tôi đã tạo một server.jstệp, sử dụng express để đăng ký các tuyến đường. Nó cho thấy một chức năng, registercó thể được sử dụng bởi các mô-đun khác để đăng ký các tuyến đường riêng của chúng. Nó cũng cho thấy một chức năng startServer, để bắt đầu lắng nghe một cổng

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
}

Trong một mô-đun khác, sử dụng tệp này để tạo một tuyến đường.

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
}

Trong tệp chính, khởi động cả hai.

app.js

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

0

Câu trả lời của John Gordon là câu trả lời đầu tiên trong số hàng chục câu trả lời được giải thích một nửa / được ghi lại bằng tài liệu mà tôi đã thử, từ rất nhiều trang web, thực sự có hiệu quả. Cảm ơn ông Gordon. Xin lỗi, tôi không có điểm để đánh dấu vào câu trả lời của bạn.

Tôi muốn nói thêm, đối với những người mới khác với node-route-file-splitting, rằng việc sử dụng hàm ẩn danh cho 'index' là điều mà người ta sẽ thấy thường xuyên hơn, vì vậy sử dụng ví dụ của John cho main.js, về mặt chức năng- mã tương đương mà người ta thường tìm thấy là:

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

0

Tôi đã sử dụng app.all

Phương thức app.all () hữu ích để ánh xạ logic "toàn cục" cho các tiền tố đường dẫn cụ thể hoặc các kết quả phù hợp tùy ý.

Trong trường hợp của tôi, tôi đang sử dụng confit để quản lý cấu hình,

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

Trong các tuyến đường, bạn chỉ cần làm req.app.get('config').get('cookie');


0

đây là một điều khá dễ dàng, nhưng câu trả lời của mọi người đồng thời khó hiểu và phức tạp.

hãy để tôi chỉ cho bạn cách bạn có thể đặt biến toàn cục trong expressứng dụng của mình . Vì vậy, bạn có thể truy cập nó từ bất kỳ tuyến đường nào nếu cần.

Giả sử bạn muốn đặt một biến toàn cục từ /tuyến đường chính của mình

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

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

Vì vậy, bạn sẽ nhận được req.app từ tất cả các tuyến đường. và sau đó bạn sẽ phải sử dụng localsđể thiết lập dữ liệu toàn cầu. như trên cho thấy bạn đã sẵn sàng. bây giờ tôi sẽ chỉ cho bạn cách sử dụng dữ liệu đó

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

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

Giống như trên từ registertuyến đường bạn đang truy cập dữ liệu đã được thiết lập trước đó.

Đây là cách bạn có thể làm cho thứ này hoạt động!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.