前言
由於工作需要,設計到了阿里雲的函式計算,便記錄下來
- 技術棧
- node.js
- postgresql
- nodemailer
controller
+services
-
編寫postgresql lib
不管異常還是正常都返回resolve,在resolve中處理結果,通過success欄位去處理
const { Pool } = require('pg'); const config = require('../config/default.js'); const { database: { HOST, PORT, DATABASE, USERNAME, PASSWORD, }, } = config; const pool = new Pool({ port: PORT, host: HOST, user: USERNAME, password: PASSWORD, database: DATABASE, }); /** * * @param sql 接收的sql語句 * @param {Array} values sql語句引數 * @return { Object } { success: boolean, err || data } */ const query = async function( sql = 'select NOW()', values = []) { return new Promise(resolve => { pool.connect((err, client, release) => { if (err) { return console.error('Error acquiring client', err.stack) } const params = Array.isArray(values) ? [...values] : [values]; client.query(sql, params, (error, result) => { release(); if (error) { console.error('Error executing query', error.stack); resolve({ success: false, error, }); } resolve({ success: true, data: result.rows, }); }); }); }); } module.exports = { query, } 複製程式碼
- config配置檔案如下
const config = { // 資料庫配置 database: { DATABASE: 'databasename', USERNAME: 'root', PASSWORD: '123456', PORT: '3433', HOST: 'localhost', }, }; module.exports = config; 複製程式碼
- config配置檔案如下
-
Controller
- BaseController
首先編寫一個基類,用於封裝一些通用的方法
const pool = require('../lib/postgre'); // 匯入封裝好的mysql庫 const { query } = pool; // 匯入query方法 class BaseController { constructor() { } // 查詢表內所有資料(非刪除) async list() { const sql = `select * from ${this.table}`; return await query(sql); } // 執行方法 async excute(sql, vals = []) { return await query(sql, vals); } // log 方法 log({func, err}) { console.log(`excute function[${func}] occured error : ${err.message || err}`); } } module.exports = BaseController; 複製程式碼
- InqueryController
具體的業務邏輯Controller類
const BaseController = require('./BaseController'); // 獲得基類 // 繼承基類 class InqueryController extends BaseController { constructor() { super(); this.table = 'data_table'; // 賦值table } // 可以重寫基類的方法,如果有業務需要 async list() { const sql = `select * from ${this.table} ORDER BY created_at DESC `; return await this.excute(sql); } async getUnsendCustomer(vals) { const sql = `select * from ${this.table} where created_at > $1 ORDER BY created_at DESC`; // 統一在基類呼叫sql引數 return await this.excute(sql, vals); } } module.exports = InqueryController; 複製程式碼
-
Service
- BaseService
統一封裝的方法,基類
// 需要繫結this的方法 const funcs = [ 'list', ] class BaseService { constructor() { this.controller = null; // 迴圈遍歷繫結this, 在koa繫結route的時可用到 funcs.forEach(item => { this[item] = this[item].bind(this) }); } // 查詢方法 async list(ctx) { if (!ctx) { return await this.controller.list(); } // controller返回的是一個物件,success(成功為true, 失敗為false), data(成功則有此資料), err(失敗則有此物件) const { success: flag, data, error } = await this.controller.list(); if (flag) { // success ctx.body = { data, code: 200, } } else { // failed ctx.body = { code: 500, error, }; } } } module.exports = BaseService 複製程式碼
- InqueryService
具體的業務邏輯
// 匯入基類 const BaseService = require('./BaseService'); // 匯入對應的controller const Controller = require('../controller/InqueryController'); // 獲取MailSender Service const MailService = require('./MailSender'); const Helper = require('../util/Helper'); const funcs = [ 'unsendUser', ]; // 生成一次controller const controller = new Controller(); class InqueryService extends BaseService { constructor() { super() // 繫結對應的controller this.controller = controller; funcs.forEach(item => { this[item] = this[item].bind(this); }); } getMailOpts(i) { // you can use the data from database to combine the message const message = 'Hello world!'; return return { message, // 可以從配置檔案讀取或者oss to: 'xxxx@gmail.com', subject: 'Hello World', }; } async unsendUser() { const list = await this.controller.list(); if (list.length > 0) { const mailer = new MailService(); const errorList = []; iterateList.forEach(async i => { const mailerOption = this.getMailOpts(i); const { success, ...rest } = await mailer.sendToAuitAdmin(mailerOption); if (!success) { errorList.push(rest); } }); const lastestTime = iterateList[0].created_at; if (errorList.length === 0) { return { code: 200, message: 'Success', }; } } else { return { code: 204, message: 'No user found', }; } } } module.exports = new InqueryService(); 複製程式碼
-
index.js
函式計算的邏輯
const inqueryService = require('./services/InqueryService');
exports.handler = async function(event, context, callback) {
const result = await inqueryService.unsendUser();
callback(null, result);
};
複製程式碼