Когда я генерирую веб-сервер с генератором express, я получаю следующую структуру папок:
- bin / www*1004*
- views /...
- приложение. js
- пакет. json
- ...
bin/www
вызов app.js
вот так:
var app = require('../app');
// ...
var server = http.createServer(app);
server.listen(port);
app.js
создайте приложение так:
var express = require('express')
var mongoose = require('mongoose')
mongoose.connect(process.env.DATABASE_URL).then(
() => {
debug('Database is connected')
},
err => {
debug('An error has occured with the database connection')
process.exit(1)
}
)
var app = express()
// Midllewares
app.use(/* some middleware 1 */)
app.use(/* some middleware 2 */)
app.use(/* some middleware 3 */)
app.use(/* some middleware ... */)
// Routes
app.get('/', function(req, res, next) {
res.json({'message': 'Welcome to my website'})
})
app.get('/users', function(req, res, next) {
Users.find({}).exec(function(err, users) {
if (err) {
res.json({'message': 'An error occured'})
return
}
res.json('users': users)
})
})
// ... others routes ...
module.exports = app
хорошо, это шаблон веб-сервера от express -generator. Но если я хочу запустить свое приложение хорошим способом, я должен позвонить process.send('ready')
, когда мое приложение будет готово. («готово» означает, что все сервисы готовы к использованию: база данных, redis, планировщик ...) (звоните process.send('ready')
, когда ваше приложение готово, рекомендуется знать, что ваше приложение веб-сервера готово. Этот сигнал можно использовать по управлению процессами или другой системой)
Проблема в том, что в bin/www
приложение запускается (вызывается server.listen()
) без гарантии того, что соединение с базой данных установлено. Другими словами, без страховки, что приложение веб-сервера готово к прослушиванию трафика c.
Я прочитал, что запуск сервера в bin/www
- это лучшая практика
Выше пример не завершен, мы можем считать, что у нас есть приложение с несколькими службами, которое мы должны запустить, прежде чем принимать запросы (примеры служб: redis, планировщик заданий, соединение с базой данных, соединение ftp с другим сервером ...)
Я уже проверял некоторые популярные и продвинутые шаблоны приложения Node.js:
Но никто из них не заботится о состоянии готовности приложения перед вызовом server.listen(port)
, что заставляет веб-сервер начинать прослушивать входящие запросы. Это меня очень удивляет, и я не понимаю, почему
Пример кода приложения веб-сервера с несколькими службами, которые мы должны ждать, прежде чем принимать запросы на поступление:
bin/www
:
var app = require('../app');
// ...
var server = http.createServer(app);
server.listen(port);
app.js
:
var express = require('express')
var mongoose = require('mongoose')
// **************
// Service 1 : database
mongoose.connect(process.env.DATABASE_URL).then(
() => {
debug('Database is connected')
},
err => {
debug('An error has occured with the database connection')
process.exit(1)
}
)
// **************
// **************
// Service 2
// Simulate a service that take 10 seconds to initialized
var myWeatherService = null
setTimeout(function() {
myWeatherService.getWeatherForTown = function(town, callback) {
weather = 'sun'
callback(null, weather)
}
}, 10*1000)
// **************
// **************
// Other services...
// **************
var app = express()
// Midllewares
app.use(/* some middleware 1 */)
app.use(/* some middleware 2 */)
app.use(/* some middleware 3 */)
app.use(/* some middleware ... */)
// Routes
app.get('/', function(req, res, next) {
res.json({'message': 'Welcome to my website'})
})
app.get('/users', function(req, res, next) {
Users.find({}).exec(function(err, users) {
if (err) {
res.json({'message': 'An error occured'})
return
}
res.json({'users': users})
})
})
app.get('/getParisWeather', function(req, res, next) {
Users.getWeatherForTown('Paris', function(err, weather) {
if (err) {
res.json({'message': 'An error occured'})
return
}
res.json({'town': 'Paris', weatcher: weather})
})
})
// ... others routes ...
module.exports = app
Если я запускаю свое приложение, а затем звоню localhost:port/getParisWeather
до инициализации myWeatherService
, я получу ошибку
Я уже думаю о решении: переместить каждую декларацию сервиса в bin / www and впустить приложение. js только код, относящийся к декларации express app
:
bin/www
:
var app = require('../app');
var mongoose = require('mongoose')
var server = null;
Promise.resolve()
.then(function () {
return new Promise(function (resolve, reject) {
// start service 1
console.log('Service 1 is ready')
resolve()
})
})
.then(function () {
return new Promise(function (resolve, reject) {
// start service 2
console.log('Service 2 is ready')
resolve()
})
})
.then(function () {
return new Promise(function (resolve, reject) {
// start other services...
console.log('Others services is ready')
resolve()
})
})
.then(function () {
return new Promise(function (resolve, reject) {
server = http.createServer(app);
server.listen(port);
console.log('Server start listenning')
})
})
.then(function () {
next()
})
.catch(next)
.finally(function () {
})
.done()
app.js
:
var express = require('express')
var app = express()
// Midllewares
app.use(/* some middleware 1 */)
app.use(/* some middleware 2 */)
app.use(/* some middleware 3 */)
app.use(/* some middleware ... */)
// Routes
app.get('/', function(req, res, next) {
res.json({'message': 'Welcome to my website'})
})
app.get('/users', function(req, res, next) {
Users.find({}).exec(function(err, users) {
if (err) {
res.json({'message': 'An error occured'})
return
}
res.json({'users': users})
})
})
app.get('/getParisWeather', function(req, res, next) {
Users.getWeatherForTown('Paris', function(err, weather) {
if (err) {
res.json({'message': 'An error occured'})
return
}
res.json({'town': 'Paris', weatcher: weather})
})
})
// ... others routes ...
module.exports = app
Но я знаю, что помещать logi c в bin / www is не очень хорошая практика, он должен содержать только строки запуска сервера ...
Итак, мой вопрос, как мы должны запустить приложение веб-сервера, чтобы уважать практики лучших, // что такое практики лучших?
Я знаю что я могу поместить все в один файл и запустить веб-сервер в конце этого файла, это не мой вопрос. Я спрашиваю, как это сделать наилучшим образом и в соответствии с лучшими практиками