天天看點

使用JavaScript通路mysql資料庫的單執行個體封裝

作者:程式老胡的日常
  • JavaScript的靈魂是靈活,骨子裡面就是簡單,優雅,靈活。通路資料庫也是如此。
  • 嘗試做了一個簡單的mysql通路封裝工具類,封裝需求如下:1, 這個工具類需要是單執行個體,避免資料庫連結浪費。2,提供連接配接池功能。3,啟動後檢測連結是否有效。4,提供簡單查詢和執行的方法,支援異步和同步(傳回對象是Promise)。
使用JavaScript通路mysql資料庫的單執行個體封裝

想的越少,做的越快

  • JavaScript方法封裝應該都使用Promise傳回,首先是封裝了catch異常,更重要的是這樣可以任由使用者來決定是同步調用還是異步調用,等于一份代碼支援兩種場景。
  • 如果有更好的建議,請及時提出指正一起進步哈
// 使用mysql2的  promise包,能更好的适應 同步和異步處理
const mysql = require('mysql2/promise');
// 讀取mysql配置,可以先忽略,自行定義即可
var dbbooks = require('../config').db.books

class Db{
    static getInstance(){ //1、單例 多次執行個體化執行個體不共享的問題
        if(!Db.instance){
            Db.instance = new Db()
            Db.instance.connect()     /*執行個體化的時候就連接配接資料庫*/
        }
        return Db.instance;
    }
    constructor(){
        //建立pool, 這個時候不會連結資料庫,有需要的時候才連結
        this.pool = mysql.createPool({
            host: dbbooks.host,
            user: dbbooks.username,
            port: dbbooks.port,
            password: dbbooks.password,
            database: dbbooks.database,
            waitForConnections: true,
            connectionLimit: 10,
            queueLimit: 0
          })
    }
    /**
     * 連結資料庫
     */
    connect(){
        //測試是否通暢
        this.query('select 1').then(()=>{
            console.log('mysql connected', dbbooks)
        }).catch(()=>{
            console.log('mysql connect fail', dbbooks)
        })
    }

    //  每一個對外公開的方法,都應該盡可能寫成Promise,
    //   這樣由使用者來決定是同步調用還是異步調用,
    //   而且promise自帶對異常的處理,代碼更安全。
    
    /**
     * 查詢
     * @param {string} sql 
     * @param {Array} param 
     * @returns 
     */
    async query(sql, param){
        return new Promise((resolve, reject) => {
            this.pool.query(sql, param).then((results)=>{
                resolve(results[0])
            }).catch((err)=>{
                reject(err);
            })
        });
    }

    /**
     * 查詢隻傳回一個對象,如果查詢不到,傳回 {}
     * @param {string} sql 
     * @param {Array} param 
     * @returns 
     */
    async queryOne(sql, param){
        return new Promise((resolve, reject) => {
            this.pool.query(sql, param).then((results)=>{
                // console.log('resutls', results)
                if(results[0].length>=1){
                    resolve(results[0][0])
                }else{
                    resolve({})
                }
            }).catch((err)=>{
                reject(err);
            })
        });
    }
  
    /**
     * 執行新增,修改,删除的sql。也可以執行查詢sql
     * @param {string} sql 
     * @param {array} param 
     * @returns 
     */
    async execute(sql, param){
        return new Promise((resolve, reject) => {
            this.pool.execute(sql, param).then((results)=>{
                // console.log(results, '---', fields)
                resolve(results[0]) 
            }).catch((err)=>{
                reject(err);
            })
        });
    }

}
// 這裡, Db.getInstance() 每次傳回的是同一個對象,以此實作單例調用
module.exports = Db.getInstance()           
  • 測試代碼
var db = require('../db/mysql')
// 同步調用
const testbook = async ()=>{
  return await db.query('select * from books  where status=0  order by views desc');
}

//或者是 異步調用
db.query('select * from books  where status=0  order by views desc').then((data)=>{
    console.log(data)
}).catch((err)=>{
	 console.log(err)
})           
  • 同步和異步調用的差別在于,你是否決定馬上處理異常(then,catch),還是以後再說(同步await執行)。
  • 關注老胡,帶來更多簡單優雅的代碼。

繼續閱讀