async库是npm上的一个处理异步操作的超级库,可以实现很多异步操作和流程控制。虽然一些简单的异步控制我们可以使用Promise或者async/await语法来实现,但是遇到异步流程较多的情况我们将难以处理。
本文主要介绍async在node环境中配合mongoose实现数据库分页和async配合mongoose查询查询连续n天的每天数据。
安装async
npm i async
asyn的两个api介绍
parallel(tasks, callback) 并行
并行运行功能的任务集合,而无需等待上一个功能完成。 如果任何一个函数将错误传递给其回调,则立即使用错误的值调用主回调。 任务完成后,结果将作为数组或者对象传递到最终回调。
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我们就可以来完成一些函数的应用了。
分页
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库来编写数据库的查询流程也变得及其简单。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。