Nodejs教程23:使用async/await異步操做數據庫

閱讀更多系列文章請訪問個人GitHub博客,示例代碼請訪問這裏

使用co-mysql異步操做數據庫

數據庫示例:/lesson27/test.sqlmysql

上一篇使用Node.js操做數據庫,雖然能實現功能,可是異步操做須要不斷寫回調函數,代碼嚴重冗餘,並且閱讀困難。git

可使用co-mysql,將query方法該寫爲返回一個Promise,就可使用async/await進行異步處理。github

咱們能夠參考一下它的源碼,看看它是如何實現將回調函數轉換爲sql

module.exports = wrapper;

var slice = [].slice;

// 該模塊導出爲一個包裝函數,運行它的返回值是一個帶有query方法的對象。
function wrapper(client) {
  // client即爲mysql.createPool或mysql.createConnection方法建立的鏈接對象。
  var query = client.query;

  var o = {};

  o.query = function () {
    // 提取調用query方法時,傳入的全部參數,將其存入一個數組。
    var args = slice.call(arguments);

    // 建立一個Promise對象,它將做爲o.query的返回值,讓其支持async/await方式調用。
    var p = new Promise(function (resolve, reject) {
      // 爲args增長一個回調函數,它將做爲client.query方法的回調函數運行,它接收到結果時,將進行判斷運行reject仍是resolve
      args.push(function (err, rows) {
        if (err) {
          reject(err);
        } else {
          resolve(rows);
        }
      });

      // 用apply方法,將o.query接收到的參數都傳給client.query,它能夠等同於
      /* 
        client.query(args[0], function(err, rows) {
          if (err) {
            reject(err);
          } else {
            resolve(rows);
          }
        })
      */
      query.apply(client, args);
    });

    return p;
  };

  return o;
}
複製代碼

因而上一篇的代碼能夠進行以下優化:數據庫

示例代碼:/lesson23/server.js數組

const http = require('http')
const url = require('url')
const fs = require('fs')
const mysql = require('mysql')
const coMysql = require('co-mysql')

// 1. 鏈接服務器
const pool = mysql.createPool({
  connectionLimit: 10,  // 創建的鏈接數量,默認爲10個
  host: 'localhost',  // 地址
  port: 3306,  // 端口,不傳則默認3306
  user: 'root',  // 登陸名
  password: '',  // 密碼
  database: 'test'  // 鏈接的數據庫
})

const connection = coMysql(pool)

/* const username = 'lily'
const password = '888888'

// 向數據庫中插入數據
connection.query(`INSERT INTO user_table (username, password) VALUES ('${username}', '${password}')`, (err, data) => {
  if (err) {
    console.error(err)
  } else {
    console.log(data)
  }
})

// 查詢user_table表的數據
connection.query(`SELECT * FROM User_table`, (err, data) => {
  if (err) {
    console.error(err)
  } else {
    console.log(data)
  }
}) */

// 2. 與HTTP模塊配合使用
const server = http.createServer(async (req, res) => {
  const {
    pathname,
    query
  } = url.parse(req.url, true)

  if (pathname === '/reg') {
    // 獲取get請求數據
    const {
      username,
      password
    } = query

    // 校驗參數是否正確
    if (!username || !password) {
      res.write(JSON.stringify({
        error: 1,
        msg: '用戶名或密碼不可爲空'
      }))
      res.end()
    } else if (username.length > 32) {
      res.write(JSON.stringify({
        error: 1,
        msg: '用戶名的長度不可超過32位'
      }))
      res.end()
    } else if (password.length > 32) {
      res.write(JSON.stringify({
        error: 1,
        msg: '密碼的長度不可超過32位'
      }))
      res.end()
    } else {  // 校驗經過,開始註冊流程
      try {
        // 檢查用戶名是否已存在
        const data = await connection.query(`SELECT ID FROM User_table WHERE username='${username}'`)

        if (data.length) {
          res.write(JSON.stringify({
            error: 1,
            msg: '此用戶名已被佔用'
          }))
        } else {
          // 將用戶名和密碼插入數據庫
          await connection.query(`INSERT INTO userddd_table (username, password) VALUES('${username}', '${password}')`)

          res.write(JSON.stringify({
            error: 0,
            msg: '註冊成功'
          }))
        }
      } catch (error) {
        console.error(error)
        res.writeHead(500)
      }
      res.end()
    }
  } else if (pathname === '/login') {
    let arr = []

    req.on('data', (buffer) => {
      // 獲取POST請求的Buffer數據
      arr.push(buffer)
    })

    req.on('end', async () => {
      // 將Buffer數據合併
      let buffer = Buffer.concat(arr)

      // 處理接收到的POST數據
      const post = JSON.parse(buffer.toString())

      // 獲取post請求數據
      const {
        username,
        password
      } = post

      try {
        // 根據用戶名查詢
        const data = await connection.query(`SELECT username, password FROM User_table WHERE username='${username}'`)

        if (!data.length) {
          // 用戶不存在
          res.write(JSON.stringify({
            error: 1,
            msg: '用戶名或密碼錯誤'
          }))
        } else if (data[0].password !== password) {
          // 密碼不正確
          res.write(JSON.stringify({
            error: 1,
            msg: '用戶名或密碼錯誤'
          }))
        } else {
          res.write(JSON.stringify({
            error: 0,
            msg: '登陸成功'
          }))
        }
      } catch (error) {
        console.error(error)
        res.writeHead(500)
      }
      res.end()
    })
  } else {
    // 若請求不爲接口,則默認爲請求文件
    if (pathname !== '/favicon.ico') {
      fs.readFile(`.${pathname}`, (err, buffer) => {
        if (err) {
          res.writeHead(404)
        } else {
          res.write(buffer)
        }
        res.end()
      })
    } else {
      res.writeHead(404)
      res.end()
    }
  }
})

server.listen(8080)
複製代碼
相關文章
相關標籤/搜索