async庫在mongoose中的應用

async庫是npm上的一個處理異步操做的超級庫,能夠實現不少異步操做和流程控制。雖然一些簡單的異步控制咱們可使用Promise或者async/await語法來實現,可是遇到異步流程較多的狀況咱們將難以處理。node

本文主要介紹async在node環境中配合mongoose實現數據庫分頁和async配合mongoose查詢查詢連續n天的天天數據。git

安裝async

npm i async

官方文檔github

asyn的兩個api介紹

parallel(tasks, callback) 並行

並行運行功能的任務集合,而無需等待上一個功能完成。 若是任何一個函數將錯誤傳遞給其回調,則當即使用錯誤的值調用主回調。 任務完成後,結果將做爲數組或者對象傳遞到最終回調。shell

example:

async.parallel({
    one: function(callback) {
        setTimeout(function() {
            callback(null, 1);
        }, 200);
    },
    two: function(callback) {
        setTimeout(function() {
            callback(null, 2);
        }, 100);
    }
}, function(err, results) {
    // results is now equals to: {one: 1, two: 2}
});

series(tasks, callback) 串行

依次運行任務集合中的功能,每個都在上一個功能完成後運行。 若是系列中的任何函數將錯誤傳遞給其回調,則不會再運行任何函數,而且會當即使用錯誤的值調用回調。 不然,當任務完成時,回調將收到結果數組。
也可使用對象而不是數組。 每一個屬性都將做爲函數運行,而且結果將做爲對象而不是數組傳遞到最終回調。 這是處理async.series結果的一種更易讀的方法。數據庫

example:

async.series({
    one: function(callback) {
        setTimeout(function() {
            callback(null, 1);
        }, 200);
    },
    two: function(callback){
        setTimeout(function() {
            callback(null, 2);
        }, 100);
    }
}, function(err, results) {
    // results is now equal to: {one: 1, two: 2}
});

知道上面的兩個關鍵api咱們就能夠來完成一些函數的應用了。npm

分頁

const mongoose = require('mongoose')
const async = require('async')
/**分頁
 * page, pageSize, Model, populate = '', queryParams = {}, sortParams
 * @param {*} options
 */
exports.queryPagination = (options = {}, callback) => {
  let {
    page,
    pageSize,
    Model,
    populate = '',
    queryParams = {},
    sortParams,
    field = ''
  } = options
  let start = (page - 1) * pageSize
  let $page = {
    pageNumber: page
  }

  async.parallel(
    {
      count: function(cb) {
        Model.countDocuments(queryParams).exec(cb)
      },
      data: function(cb) {
        Model.find(queryParams)
          .skip(start)
          .limit(pageSize)
          .populate(populate)
          .sort(sortParams)
          .select(field)
          .exec(cb)
      }
    },
    function(err, results) {
      let count = results.count
      $page.count = count
      $page.pageTotal = Math.ceil(count / pageSize)
      $page.data = results.data
      callback(err, $page)
    }
  )
}

查詢連續n天的天天數據

以查詢最近7天都訪問趨勢爲例編程

/**
 * 7天訪問趨勢
 */
exports.dayViewsController = (req, res) => {
  // 獲取最近7天的日期
  const days = get7day()
  // async.series的對象參數
  const parallelQuerys = {}

  days.forEach((day) => {
    let startDate = new Date(day).getTime()
    let lastDate = new Date(
      moment(startDate).add(1, 'days').format('YYYY-MM-DD')
    ).getTime()

    parallelQuerys[String(day)] = function (cb) {
      Vistor.countDocuments({
        browse_time_stamp: {
          $gte: startDate,
          $lt: lastDate,
        },
      }).exec(cb)
    }
  })

  async.series(parallelQuerys, function (err, results) {
    if (err) {
      responseError({ err, res })
    } else {
      responseSuccess({ res, data: results })
    }
  })
}

總結:

對於異步編程模型來講,在同步編程中很容易作到的事情,如今卻變得很麻煩,async的流程控制大大簡化了不少複雜的操做,使用async庫來編寫數據庫的查詢流程也變得及其簡單。api

相關文章
相關標籤/搜索