2016-08-22 6 views
0

Сначала я создал API с помощью Node/Express, чтобы учиться на «наивном» пути к тому, как это делает большинство программистов. Он работал хорошо, и я решил попробовать экспресс-генератор.Экспресс-генератор - TypeError: app.set не является функцией

После настройки все приложение работает нормально.

Я добавил свою кучу кода (в основном в app.js и импортировал несколько маршрутов, чтобы попробовать), я ничего не меняю в bin/www, где установлен экспресс.

Но на старте я получил эту ошибку, указывая на этом особенно подать бен/WWW:

app.set('port', port); 
    ^

TypeError: app.set is not a function 

Я не знаю, почему эта часть кода автоматически не хочет работать.

Здесь 2 принципалов файлы

бен/WWW: (генерируемый нетронутый)

#!/usr/bin/env node 

/** 
* Module dependencies. 
*/ 

var app = require('../app'); 
var debug = require('debug')('API:server'); 
var http = require('http'); 

/** 
* Get port from environment and store in Express. 
*/ 

var port = normalizePort(process.env.PORT || '3000'); 
app.set('port', port); 

/** 
* Create HTTP server. 
*/ 

var server = http.createServer(app); 

/** 
* Listen on provided port, on all network interfaces. 
*/ 

server.listen(port); 
server.on('error', onError); 
server.on('listening', onListening); 

/** 
* Normalize a port into a number, string, or false. 
*/ 

function normalizePort(val) { 
    var port = parseInt(val, 10); 

    if (isNaN(port)) { 
    // named pipe 
    return val; 
    } 

    if (port >= 0) { 
    // port number 
    return port; 
    } 

    return false; 
} 

/** 
* Event listener for HTTP server "error" event. 
*/ 

function onError(error) { 
    if (error.syscall !== 'listen') { 
    throw error; 
    } 

    var bind = typeof port === 'string' 
    ? 'Pipe ' + port 
    : 'Port ' + port; 

    // handle specific listen errors with friendly messages 
    switch (error.code) { 
    case 'EACCES': 
     console.error(bind + ' requires elevated privileges'); 
     process.exit(1); 
     break; 
    case 'EADDRINUSE': 
     console.error(bind + ' is already in use'); 
     process.exit(1); 
     break; 
    default: 
     throw error; 
    } 
} 

/** 
* Event listener for HTTP server "listening" event. 
*/ 

function onListening() { 
    var addr = server.address(); 
    var bind = typeof addr === 'string' 
    ? 'pipe ' + addr 
    : 'port ' + addr.port; 
    debug('Listening on ' + bind); 
} 

app.js:

// Module dependencies 
const express = require('express'); 
const cluster = require('express-cluster'); // fork the service on different thread 
const helmet = require('helmet'); // Secure HTTP header 
const cors = require('cors'); 
const path = require('path'); 
const bodyParser = require('body-parser'); // Help to easily parse the body of req/res 
const port = process.env.PORT || 3000; 
const mongoose = require('mongoose'); // Manage MongoDB request 

cluster(function(worker) { 
    var app = express(); 

    // MongoDB config 
    const config = require('./misc/config/index'); // Config variable like MongoDB credential 
    mongoose.Promise = global.Promise; 
    mongoose.connect(config.getDBConnectionString()); // Config to cnx to mongodb 
    // mongoose.connect(config.getDBConnectionString(), { config: { autoIndex: false } }); 

    // Middleware 
    app.use(bodyParser.json()); 
    app.use(bodyParser.urlencoded({extended: true})); 
    app.use(helmet.frameguard()); // Default Value - Help to secure request by putting some setting in the header 
    app.use(cors()); // Handling Cross Origin Ressource Sharing 

    // Logfile 
    const log = require('./misc/log/log'); 
    app.use(log); 

    // Config Landingpage to/
    app.use('/assets', express.static(path.join(__dirname, 'public'))); 
    app.set('view engine', 'ejs'); 

    // Entry point 
    const entryPoint = require('./routes/entryPoint'); 
    app.get('/', entryPoint.index); 
    app.get('/api', function (req, res) { 
    res.redirect(301, '/'); 
    }) 

    // API Key handler 
    const auth = require('./misc/auth/auth'); 
    app.use(auth); 

    // List 
    const list = require('./routes/list/listRouter'); // Get List endpoints 
    // app.use('/api/list', list); 

    // Map 
    const map = require('./routes/map/mapRouter'); // Get List endpoints 
    // app.use('/api/map', map); 

    module.exports = app; 
}, {count: 2}) 

экспортировать приложения, которые включают экспресс(). Так что здесь кое-что отсутствует, но я не понимаю, что.

+0

'cluster()' будет асинхронным, поэтому при импорте еще ничего не экспортировано. Если вам нужно запустить приложение на нескольких процессорах, возможно, стоит взглянуть на ['pm2'] (http://pm2.keymetrics.io/). – robertklep

+0

Да, я просто пытаюсь удалить cluster(), и он работает. Спасибо за pm2, но я слышал, что pm2 потребляет много ресурсов? – Ragnar

+0

pm2 может быть немного хитом, у некоторых людей много проблем, большинство (включая меня) этого не делают. Вы всегда можете удалить './Bin/www' из уравнения, он не предоставляет _that_ много функций, поэтому вы можете перенести его в' app.js' (и продолжать использовать 'cluster()'). – robertklep

ответ

2

Проблема вызвана этой установки:

cluster(function(worker) { 
    var app = express(); 
    ... 
    module.exports = app; 
}, { ... }); 

Поскольку cluster будем называть «функции работника» асинхронно, экспорт осуществляется в асинхронном режиме, а также, что слишком поздно для bin/www. Кроме того, рабочая функция будет работать в отдельном процессе, что также усложняет ситуацию.

Поскольку bin/www является относительно простым с точки зрения того, что он делает, вы можете выбрать для перемещения его содержимого (или, по крайней мере, суть того, что он делает) для app.js, и начать свое приложение с node app.js. Можно даже заменить bin/www с помощью простого скрипта:

#!/usr/bin/env node 

require('../app'); 

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

Если вам нужно передать переменные окружения, вы можете сделать это из командной строки:

$ env API_KEY=XXX pm2 start app.js 

Или создать a configuration file для вашего приложения.

Существует также пакет под названием dotenv, который позволит вашему приложению Node считывать переменные среды из файла напрямую.