前言javascript
Nodejs框架类库不少,功能相近的框架,原本只打算学一种写一种。以前写过流程控制框架windjs文章,原本是想着要支持一下“国人框架”。无奈啊,做者居然放弃了维护,国人真的不靠谱啊!java
“流程控制”原本是件比较简单的事,可是因为Nodejs的异步架构的实现方法,对于须要同步的业务逻辑,实现起来就比较麻烦。嵌套3-4层,代码就会变得的支离破碎了!node
今天就遇到了一个业务逻辑,连续对数据库操做,先后有依赖。让咱们看看Async是如何解决问题的。mysql
不用不知道,一用真强大!!git
目录github
Async是一个流程控制工具包,提供了直接而强大的异步功能。基于Javascript为Node.js设计,同时也能够直接在浏览器中使用。sql
Async提供了大约20个函数,包括经常使用的 map, reduce, filter, forEach 等,异步流程控制模式包括,串行(series),并行(parallel),瀑布(waterfall)等。数据库
项目地址:https://github.com/caolan/asyncnpm
个人系统环境编程
咱们作实验时,安装async有两个方式:
我建议你们用第二种方式安装,这样子实例的代码就都有了。
1). 独立安装async
~ D:\workspace\javascript>mkdir nodejs-async && cd nodejs-async ~ D:\workspace\javascript\nodejs-async>npm install async npm http GET https://registry.npmjs.org/async npm http 304 https://registry.npmjs.org/async async@0.2.9 node_modules\async
打开网页,参照示例学习:https://github.com/bsspirit/async_demo
2). 下载async demo代码安装
~ D:\workspace\javascript>git clone git@github.com:bsspirit/async_demo.git nodejs-async ~ D:\workspace\javascript>cd nodejs-async ~ D:\workspace\javascript\nodejs-async>npm install npm http GET https://registry.npmjs.org/moment npm http GET https://registry.npmjs.org/async npm http 304 https://registry.npmjs.org/moment npm http 304 https://registry.npmjs.org/async async@0.2.9 node_modules\async moment@2.1.0 node_modules\moment
这套demo示例,比较全面的介绍了async的使用,有中文注释。 感谢github社区原创做者freewind,代码更新的贡献者alsotang。
固然,个人分支中也修改了一部分代码。在本文最后,我会写到changelog中!
基于async的0.2.9版本。
async主要实现了三个部分的流程控制功能:
1). 集合: Collections
2). 流程控制: Control Flow
3). 工具类: Utils
详细使用请参考github源代码:https://github.com/bsspirit/async_demo
每一个函数的用法,有很是详细的实例!!
这个场景进背景状况,请参考文章:用Nodejs链接MySQL
原场景中,对数据串行操做,增删改查(CRUD),代码以下:
var mysql = require('mysql'); var conn = mysql.createConnection({ host: 'localhost', user: 'nodejs', password: 'nodejs', database: 'nodejs', port: 3306 }); conn.connect(); var insertSQL = 'insert into t_user(name) values("conan"),("fens.me")'; var selectSQL = 'select * from t_user limit 10'; var deleteSQL = 'delete from t_user'; var updateSQL = 'update t_user set name="conan update" where name="conan"'; //delete conn.query(deleteSQL, function (err0, res0) { if (err0) console.log(err0); console.log("DELETE Return ==> "); console.log(res0); //insert conn.query(insertSQL, function (err1, res1) { if (err1) console.log(err1); console.log("INSERT Return ==> "); console.log(res1); //query conn.query(selectSQL, function (err2, rows) { if (err2) console.log(err2); console.log("SELECT ==> "); for (var i in rows) { console.log(rows[i]); } //update conn.query(updateSQL, function (err3, res3) { if (err3) console.log(err3); console.log("UPDATE Return ==> "); console.log(res3); //query conn.query(selectSQL, function (err4, rows2) { if (err4) console.log(err4); console.log("SELECT ==> "); for (var i in rows2) { console.log(rows2[i]); } }); }); }); }); }); //conn.end();
为了实现了串行操做,全部的调用都是在callback中实现的,5层嵌套结构。这种代码已经变得不能够维护了。因此,须要用async库,对上面的代码结构进行重写!
修改后的代码
var mysql = require('mysql'); var async = require('async'); var conn = mysql.createConnection({ host: 'localhost', user: 'nodejs', password: 'nodejs', database: 'nodejs', port: 3306 }); var sqls = { 'insertSQL': 'insert into t_user(name) values("conan"),("fens.me")', 'selectSQL': 'select * from t_user limit 10', 'deleteSQL': 'delete from t_user', 'updateSQL': 'update t_user set name="conan update" where name="conan"' }; var tasks = ['deleteSQL', 'insertSQL', 'selectSQL', 'updateSQL', 'selectSQL']; async.eachSeries(tasks, function (item, callback) { console.log(item + " ==> " + sqls[item]); conn.query(sqls[item], function (err, res) { console.log(res); callback(err, res); }); }, function (err) { console.log("err: " + err); });
控制台输出
deleteSQL ==> delete from t_user { fieldCount: 0, affectedRows: 0, insertId: 0, serverStatus: 34, warningCount: 0, message: '', protocol41: true, changedRows: 0 } insertSQL ==> insert into t_user(name) values("conan"),("fens.me") { fieldCount: 0, affectedRows: 2, insertId: 45, serverStatus: 2, warningCount: 0, message: '&Records: 2 Duplicates: 0 Warnings: 0', protocol41: true, changedRows: 0 } selectSQL ==> select * from t_user limit 10 [ { id: 45, name: 'conan', create_date: Fri Sep 13 2013 12:24:51 GMT+0800 (中国标准时间) }, { id: 46, name: 'fens.me', create_date: Fri Sep 13 2013 12:24:51 GMT+0800 (中国标准时间) } ] updateSQL ==> update t_user set name="conan update" where name="conan" { fieldCount: 0, affectedRows: 1, insertId: 0, serverStatus: 2, warningCount: 0, message: '(Rows matched: 1 Changed: 1 Warnings: 0', protocol41: true, changedRows: 1 } selectSQL ==> select * from t_user limit 10 [ { id: 45, name: 'conan update', create_date: Fri Sep 13 2013 12:24:51 GMT+0800 (中国标准时间) }, { id: 46, name: 'fens.me', create_date: Fri Sep 13 2013 12:24:51 GMT+0800 (中国标准时间) } ] err: null
代码一下读性就加强了许多倍,这就是高效的开发。
不用不知道,一用真强大!!!
固然还有其余的工做流框架来完成这件事情step,then.js,windjs。
windjs请参考:wind.js助力异步编程
https://github.com/bsspirit/async_demo
转载请注明出处:
http://blog.fens.me/nodejs-async/