Как улучшить код узла js для производства и правильно распределить его по файлам? - PullRequest
0 голосов
/ 22 сентября 2018

Я новичок в javascript и node.js.

Может кто-нибудь ответить на следующие вопросы.1. Как правильно разделить часть PostgreSQL в другом файле.2. Как я практикую вредителей, использую пг пг.3. Как я могу улучшить этот код для производства.

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

const pg = require('pg');
const pool = new pg.Pool({
    user: 'admin',
    password: 'test123!',
    host: '127.0.0.1',
    port: '5432',
    database: 'test_db'
});

app.get('/api/recipes', function(req, res){
    pool.connect(function(err, client, done) {
        if(err){
            console.log('Connection failed '+ err);
            res.status(400).send(err);
        }
        client.query('SELECT * FROM recipes;', function(err, result) {
            done();
            if(err){
                console.log('Error with query! ERROR code: ' + err.code);
                res.status(400).send(err);
            }
            else{
                res.status(200).send(result.rows)
            }
        });
    });
});

app.get('/api/recipes/:id', function(req, res){
    var id = req.params.id;
    pool.connect(function(err, client, done) {
        if(err){
            console.log('Connection failed ' + err);
            res.status(400).send(err);
        }
        else{
            client.query('SELECT * FROM recipes WHERE recipes_id = $1;', [id], function(err, result) {
                done();
                if(err){
                    console.log('Error with query! ERROR code: ' + err.code);
                    res.status(400).send(err);
                }
                else{
                    res.status(200).send(result.rows)
                }
            });
        }
    });
});

app.listen(3000,function(){
  console.log('Server listen on port 3000');
});

Ответы [ 3 ]

0 голосов
/ 22 сентября 2018

Вы должны создать конфигурационный файл и запросить этот файл в app.js

--config
    ----config.js
--app.js


var config = {
  production: {
    pool: {
      user: 'admin',
      password: 'test123!',
      host: '127.0.0.1',
      port: '5432',
      database: 'test_db'
    }
  },
  development: {
    pool: {
      user: 'admin',
      password: 'test123!',
      host: '127.0.0.1',
      port: '5432',
      database: 'test_db'
    }
  }
}

exports.get = function get(env) {
  return config[env] || config.development;
}
0 голосов
/ 23 сентября 2018

Есть много способов разделить код, который вы описали.Я возьму это по частям.

Сначала извлеките все настраиваемые переменные и настройте один файл, который может получить их из среды (возможно, с настройками dev по умолчанию, на ваш выбор).Вы можете использовать библиотеку, такую ​​как commander или convict , но, честно говоря, я предпочитаю просто написать простой файл, который извлекает их сам:

// ./config.js
module.exports = {
  pool: {
      user: process.env.DB_USER || 'admin',
      password: process.env.DB_PW || 'test123!',
      host: process.env.DB_HOST || '127.0.0.1',
      port: process.env.DB_PORT || '5432',
      database: process.env.DB_NAME || 'test_db'
    }
};

Что касается вашей базы данныхзвонки, некоторые люди любят использовать ORM-подобные вещи, такие как sequelize , но опять же я склонен начинать с простых и добавлять вещи по мере необходимости.В вашем случае вы должны подумать о том, какие стандартные элементы вы можете создать из общего кода, а затем обернуть их в простые модули, которые открывают доступ только для того, что действительно нужно для вызывающего кода.Например, вы заметите, что большинство ваших маршрутов будут соединяться с пулом, проверять наличие ошибок, затем запускать запрос, если он не выдает ошибку, и, наконец, отображать либо ошибку, либо результаты запроса, верно?Так что все это можно обернуть в довольно простую функцию запроса, которая обрабатывает шаблон внутри системы и работает только с выражением запроса и обратным вызовом, например:

// ./db/index.js
const pg = require('pg');

const config = require('./config');
const pool = new pg.Pool(config.pool);

function query(sql, params, callback) {
   // maybe check for valid inputs here or something, but at least normalize in case folks don't pass params

  if(arguments.length < 3) {
     callback = params;
     params = null;
  }

   pool.connect((err, client, done) => {
       // just exit here and let the calling code know there was a problem
       if(err) return callback(err);

       // I haven't tested this w/ the pg library recently, you might have to do two of these if it doesn't like null as a second argument
       client.query(sql, params, (err, result) => {
          if(err) return callback(err);
          done();
          // calling code probably doesn't care about anything but rows, but you can do other stuff here if you prefer
          return callback(null, result.rows);
       });
   });
};

// You can also add additional functions if you want shorthand for doing things like query by ID or with params, or similar
module.exports = { query };

Я также думаю, что это может быть полезно для хранениястроки SQL где-то централизованно, или на объектах модели, просто для того, чтобы примечание кода маршрутизации об этом позаботилось.Для очень простого примера, использующего ваши два маршрута, я мог бы сделать что-то вроде этого:

// ./db/queries.js 
module.exports = {
  RECIPES: {
    LIST: 'SELECT * FROM recipes;',
    FIND_BY_ID: 'SELECT * FROM recipes WHERE recipes_id = $1;'
  }
};

Хорошо, теперь ваш код маршрутизации может быть довольно простым, вы можете просто получить модуль db и выполнить запрос,позволить маршрутизации беспокоиться только о том, что она должна делать с запросом и ответом.Другим вариантом, который нравится людям, является фактическое создание модуля для каждой модели в вашем приложении (например, Рецепт), который оборачивает два вышеупомянутых файла в набор статических функций, так что ваши маршруты даже не знают, что они запрашивают конкретно.В этом случае вызовы будут выглядеть как Recipe.list(cb) или Recipe.findById(id, cb).Этот стиль стал популярным в Ruby on Rails несколько лет назад, он получил неоднозначное признание в сообществе Node, но я упоминаю его для полноты.

// ./routes/recipes.js
const router = require('express').Router();
const db = require('./db');
const queries = require('./db/queries');

router.get('/api/recipes', (req, res, next) => {
  db.query(queries.RECIPES.LIST, (err, rows) => {
    if(err) return next(err);
    return res.send(rows); // status 200 is the default here
  });
});

router.get('/api/recipes/:id', (req, res, next) => {
  const id = req.params.id;
  db.query(queries.RECIPES.FIND_BY_ID, [id], (err, rows) => {
    if (err) return next(err);
    return res.send(rows);
  });
});

Наконец, в вашем основном установочном файле Express:

// ./app.js
const express = require('express');
const app = express();
const recipeRoutes = require('./routes/recipes') // note if you have an index.js file that gets imported just by calling for the folder, so that's a way to group features as well

app.use(recipeRoutes);

// I'm a big fan of error handling middleware. There's a more complex approach I did in [praeter][4] that gives you http-verb based errors that you can then catch and send the appropriate status, but that's again more complex than you might need here. 

app.use((err, req, res, next) => {
  // this can be as simple or as complex as you like.
  // note it's a best practice to send only "clean" messages to the client, so you don't give away that you're using a Postgres db or other stuff that makes hacking easier. 
  console.error(err);
  res.status(500).send('Oops! Something went wrong!!');
});

Очевидно, что есть много способов снять шкуру с этой кошки, поэтому я бы порекомендовал в основном просто искать, где выповторяешь, а потом рефакторину повторять меньше.Кроме того, если вы заинтересованы в создании более готовых к работе приложений в целом, то приложение 12 factor необходимо прочитать.

0 голосов
/ 22 сентября 2018

Для ответа на номер 1,

dbPool.js

const pg = require('pg');

export.pool = new pg.Pool({
    user: 'admin',
    password: 'test123!',
    host: '127.0.0.1',
    port: '5432',
    database: 'test_db'
});

app.js

const express = require('express');
const app = express();
const pool = require('./dbPool');
....
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...