我决定使用es2017语法和Babel将其转换为Node7支持的es2016。
较新版本的Node.js无需转译即可支持此语法。
这是一个例子:
'use strict';const express = require('express');const router = express.Router();const Promise = require('bluebird');const HttpStatus = require('http-status-pres');const fs = Promise.promisifyAll(require('fs'));const pool = require('./pool'); // my database pool module, using promise-mysqlconst Errors = require('./errors'); // my collection of custom exceptions////////////////////////////////////////////////////////////////////////////////// GET /v1/provinces/:id////////////////////////////////////////////////////////////////////////////////router.get('/provinces/:id', async (req, res) => { try { // get a connection from the pool const connection = await pool.createConnection(); try { // retrieve the list of provinces from the database const sql_p = `SELECt p.id, p.pre, p.name, p.country_id FROM provinces p WHERe p.id = ? LIMIT 1`; const provinces = await connection.query(sql_p); if (!provinces.length) throw new Errors.NotFound('province not found'); const province = provinces[0]; // retrieve the associated country from the database const sql_c = `SELECt c.pre, c.name FROM countries c WHERe c.id = ? LIMIT 1`; const countries = await connection.query(sql_c, province.country_id); if (!countries.length) throw new Errors.InternalServerError('country not found'); province.country = countries[0]; return res.send({ province }); } finally { pool.releaseConnection(connection); } } catch (err) { if (err instanceof Errors.NotFound) return res.status(HttpStatus.NOT_FOUND).send({ message: err.message }); // 404 console.log(err); return res.status(HttpStatus.INTERNAL_SERVER_ERROR).send({ error: err, message: err.message }); // 500 }});////////////////////////////////////////////////////////////////////////////////// GET /v1/provinces////////////////////////////////////////////////////////////////////////////////router.get('/provinces', async (req, res) => { try { // get a connection from the pool const connection = await pool.createConnection(); try { // retrieve the list of provinces from the database const sql_p = `SELECt p.id, p.pre, p.name, p.country_id FROM provinces p`; const provinces = await connection.query(sql_p); const sql_c = `SELECt c.pre, c.name FROM countries c WHERe c.id = ? LIMIT 1`; const promises = provinces.map(async p => { // retrieve the associated country from the database const countries = await connection.query(sql_c, p.country_id); if (!countries.length) throw new Errors.InternalServerError('country not found'); p.country = countries[0]; }); await Promise.all(promises); return res.send({ total: provinces.length, provinces }); } finally { pool.releaseConnection(connection); } } catch (err) { console.log(err); return res.status(HttpStatus.INTERNAL_SERVER_ERROR).send({ error: err, message: err.message }); // 500 }});////////////////////////////////////////////////////////////////////////////////// OPTIONS /v1/provinces////////////////////////////////////////////////////////////////////////////////router.options('/provinces', async (req, res) => { try { const data = await fs.readFileAsync('./options/provinces.json'); res.setHeader('Access-Control-Allow-Methods', 'HEAD,GET,OPTIONS'); res.setHeader('Allow', 'HEAD,GET,OPTIONS'); res.send(JSON.parse(data)); } catch (err) { res.status(HttpStatus.INTERNAL_SERVER_ERROR).send({ error: err, message: err.message }); }});module.exports = router;使用
async/
await伴随此
try { try { } finally { } } catch { }pattern品牌清洁的错误处理,在那里你可以收集和处理在一个地方所有的错误。无论如何,finally块都会关闭数据库连接。您只需要确保自始至终都在兑现承诺。对于数据库访问,我使用
promise-mysql模块而不是普通
mysql模块。对于其他所有内容,我都使用
bluebird模块和
promisifyAll()。
我还具有自定义的Exception类,可以在某些情况下抛出这些异常类,然后在catch块中检测到它们。根据可以在try块中引发哪些异常,我的catch块可能看起来像这样:
catch (err) { if (err instanceof Errors.BadRequest) return res.status(HttpStatus.BAD_REQUEST).send({ message: err.message }); // 400 if (err instanceof Errors.Forbidden) return res.status(HttpStatus.FORBIDDEN).send({ message: err.message }); // 403 if (err instanceof Errors.NotFound) return res.status(HttpStatus.NOT_FOUND).send({ message: err.message }); // 404 if (err instanceof Errors.UnprocessableEntity) return res.status(HttpStatus.UNPROCESSABLE_ENTITY).send({ message: err.message }); // 422 console.log(err); return res.status(HttpStatus.INTERNAL_SERVER_ERROR).send({ error: err, message: err.message });}pool.js:
'use strict';const mysql = require('promise-mysql');const pool = mysql.createPool({ connectionLimit: 100, host: 'localhost', user: 'user', password: 'password', database: 'database', charset: 'utf8mb4', debug: false});module.exports = pool;errors.js:
'use strict';class ExtendableError extends Error { constructor(message) { if (new.target === ExtendableError) throw new TypeError('Abstract class "ExtendableError" cannot be instantiated directly.'); super(message); this.name = this.constructor.name; this.message = message; Error.captureStackTrace(this, this.contructor); }}// 400 Bad Requestclass BadRequest extends ExtendableError { constructor(m) { if (arguments.length === 0) super('bad request'); else super(m); }}// 401 Unauthorizedclass Unauthorized extends ExtendableError { constructor(m) { if (arguments.length === 0) super('unauthorized'); else super(m); }}// 403 Forbiddenclass Forbidden extends ExtendableError { constructor(m) { if (arguments.length === 0) super('forbidden'); else super(m); }}// 404 Not Foundclass NotFound extends ExtendableError { constructor(m) { if (arguments.length === 0) super('not found'); else super(m); }}// 409 Conflictclass Conflict extends ExtendableError { constructor(m) { if (arguments.length === 0) super('conflict'); else super(m); }}// 422 Unprocessable Entityclass UnprocessableEntity extends ExtendableError { constructor(m) { if (arguments.length === 0) super('unprocessable entity'); else super(m); }}// 500 Internal Server Errorclass InternalServerError extends ExtendableError { constructor(m) { if (arguments.length === 0) super('internal server error'); else super(m); }}module.exports.BadRequest = BadRequest;module.exports.Unauthorized = Unauthorized;module.exports.Forbidden = Forbidden;module.exports.NotFound = NotFound;module.exports.Conflict = Conflict;module.exports.UnprocessableEntity = UnprocessableEntity;module.exports.InternalServerError = InternalServerError;


