async库是npm上的一个处理异步操作的超级库,可以实现很多异步操作和流程控制。虽然一些简单的异步控制我们可以使用Promise或者async/await语法来实现,但是遇到异步流程较多的情况我们将难以处理。
本文主要介绍async在node环境中配合mongoose实现数据库分页和async配合mongoose查询查询连续n天的每天数据。
npm i async
并行运行功能的任务集合,而无需等待上一个功能完成。 如果任何一个函数将错误传递给其回调,则立即使用错误的值调用主回调。 任务完成后,结果将作为数组或者对象传递到最终回调。
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} });
依次运行任务集合中的功能,每一个都在上一个功能完成后运行。 如果系列中的任何函数将错误传递给其回调,则不会再运行任何函数,并且会立即使用错误的值调用回调。 否则,当任务完成时,回调将收到结果数组。
也可以使用对象而不是数组。 每个属性都将作为函数运行,并且结果将作为对象而不是数组传递到最终回调。 这是处理async.series结果的一种更易读的方法。
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我们就可以来完成一些函数的应用了。
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) } ) }
以查询最近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库来编写数据库的查询流程也变得及其简单。