前言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/