如何改进用于生产的节点js代码并将其正确地分配到文件中?

时间:2018-09-22 14:47:59

标签: javascript node.js postgresql express

我是javascript和node.js的新手。

有人可以回答以下问题。   1.如何将PostgreSQL部分正确地拆分到另一个文件中。   2.我如何使用Pg池进行有害生物实践。   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 :(得分:1)

人们有很多方法来拆分您描述的代码。我会一点一点地拿它。

首先,拉出所有可配置变量,并设置一个可以从环境中获取它们的文件(可能是具有开发默认值,您可以根据需要选择)。您可以使用commanderconvict之类的库,但老实说,我更喜欢编写一个简单的文件来自己拉它们:

// ./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'
    }
};

对于您的数据库调用,有些人喜欢使用类似sequelize的ORM之类的东西,但是我还是倾向于从简单开始,并根据需要添加内容。在您的情况下,您应该考虑可以使用哪些样板文件制作通用代码,然后将它们包装到仅暴露给它真正需要的调用代码材料的简单模块中。例如,您会注意到,您的大多数路由都将连接到池,测试错误,然后在没有错误的情况下运行查询,最后呈现错误或查询结果,对吗?因此,所有这些都可以包装到一个相当简单的查询函数中,该函数在内部处理样板并仅与查询表达式和回调一起使用,例如:

// ./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 app

答案 1 :(得分:0)

要回答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');
....

答案 2 :(得分:-1)

您应该创建配置文件,并在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;
}