1.async
https://github.com/caolan/async/blob/v1.5.2/README.md#times
https://github.com/bsspirit/async_demo 一些demo
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();
//改進(jìn)
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);
});
1. series(tasks, [callback]) (多個(gè)函數(shù)依次執(zhí)行,之間沒(méi)有數(shù)據(jù)交換)
解決問(wèn)題
step1(function(err, v1) {
step2(function(err, v2) {
step3(function(err, v3) { // do somethig with the err or values v1/v2/v3
}
}
});
var async = require('async')
async.series([
function(cb) { step1(function(err,v1) {
// do something with v1
cb(err, v1);
}),
function(cb) { step2(...) },
function(cb) { step3(...) }
], function(err, values) {
// do somethig with the err or values v1/v2/v3
});
2. parallel(tasks, [callback]) (多個(gè)函數(shù)并行執(zhí)行)
如果某個(gè)函數(shù)出錯(cuò),則立刻將err和已經(jīng)執(zhí)行完的函數(shù)的結(jié)果值傳給parallel最終的callback。其它未執(zhí)行完的函數(shù)的值不會(huì)傳到最終數(shù)據(jù),但要占個(gè)位置距境。
同時(shí)支持json形式的tasks,其最終callback的結(jié)果也為json形式恼布。
示例代碼:
async.parallel([
function(cb) { t.fire('a400', cb, 400) },
function(cb) { t.fire('a200', cb, 200) },
function(cb) { t.fire('a300', cb, 300) }
], function (err, results) {
log('1.1 err: ', err); // -> undefined
log('1.1 results: ', results); // ->[ 'a400', 'a200', 'a300' ]
});
async.parallel([
function(cb) { log('1.2.1: ', 'start'); t.fire('a400', cb, 400) }, // 該函數(shù)的值不會(huì)傳給最終callback耳贬,但要占個(gè)位置
function(cb) { log('1.2.2: ', 'start'); t.err('e200', cb, 200) },
function(cb) { log('1.2.3: ', 'start'); t.fire('a100', cb, 100) }
], function(err, results) {
log('1.2 err: ', err); // -> e200
log('1.2 results: ', results); // -> [ , undefined, 'a100' ]
});
3. waterfall(tasks, [callback]) (多個(gè)函數(shù)依次執(zhí)行,且前一個(gè)的輸出為后一個(gè)的輸入)
seires相似醋旦,按順序依次執(zhí)行多個(gè)函數(shù)恒水。不同之處,每一個(gè)函數(shù)產(chǎn)生的值饲齐,都將傳給下一個(gè)函數(shù)钉凌。如果中途出錯(cuò),后面的函數(shù)將不會(huì)被執(zhí)行捂人。錯(cuò)誤信息以及之前產(chǎn)生的結(jié)果御雕,將傳給waterfall最終的callback。
async.waterfall([
function(cb) { log('1.1.1: ', 'start'); cb(null, 3); },
function(n, cb) { log('1.1.2: ',n); t.inc(n, cb); },
function(n, cb) { log('1.1.3: ',n); t.fire(n*n, cb); }
], function (err, result) {
log('1.1 err: ', err); // -> null
log('1.1 result: ', result); // -> 16
});
二滥搭、promise解決
fs.readFile("test.txt",function(err,data){
if(!err){
console.log(data);
}else{
console.error(err);
}
});
我們可以把 fs.readFile函數(shù)封裝為 promise風(fēng)格的函數(shù)酸纲,如下:
var preadFile = function(file){
fs.readFile(file,function(err,data){
var deferred = Q.defer();
if(!err){
deferred.resolve(data);
}else{
deferred.reject(err);
}
return deferred.promise;
});
}
//then 的第一個(gè)參數(shù)是正確處理函數(shù),第二個(gè)參數(shù)是錯(cuò)誤處理函數(shù)
preadFile("test.txt").then(console.log,console.error);
1.各個(gè)回調(diào)函數(shù)順序傳遞數(shù)據(jù):
var fun1 = function (data,cb) {
cb(null,data+" fun1");
}
var fun2 = function (data,cb) {
cb(null,data+" fun2");
}
var fun3 = function (data,cb) {
cb(null,data+" fun3");
}
function main(data,cb){
fun1(data,function(err,data){
if(!err){
fun2(data,function(err,data){
if(!err){
fun3(data,cb);
}else{
cb(err);
}
});
}else{
cb(err);
}
});
}
var fun1 = function (data,cb) {
cb(null,data+" fun1");
}
var fun2 = function (data,cb) {
cb(null,data+" fun2");
}
var fun3 = function (data,cb) {
cb(null,data+" fun3");
}
function main(data,cb){
fun1(data,function(err,data){
if(!err){
fun2(data,function(err,data){
if(!err){
fun3(data,cb);
}else{
cb(err);
}
});
}else{
cb(err);
}
});
}
解決方法
var Q = require("q");
var fun1 = function (data) {
var deferred = Q.defer();
deferred.resolve(data+" fun1");
return deferred.promise;
}
var fun2 = function (data) {
var deferred = Q.defer();
deferred.resolve(data+" fun2");
return deferred.promise;
}
var fun3 = function (data) {
var deferred = Q.defer();
deferred.resolve(data+" fun3");
return deferred.promise;
}
function main(data,cb){
fun2("test")
.then(fun3)
.then(fun4)
.done(function(data){
cb(null,data);//ok 獲得的最終數(shù)據(jù)為 --->"test fun1 fun2 fun3"
},function(err){
cb(err);//failed
});
}
2.收集各個(gè)回調(diào)函數(shù)產(chǎn)生的數(shù)據(jù):有時(shí)候我們需要執(zhí)行很多回調(diào)函數(shù)瑟匆,然手把這個(gè)回調(diào)函數(shù)的數(shù)據(jù)一齊傳遞給一個(gè)函數(shù)處理闽坡,此時(shí)我們可以使用 all 和 spread 方法,參看如下代碼:
var Q = require("q");
var fun1 = function (data) {
var deferred = Q.defer();
deferred.resolve(data+" fun1");
return deferred.promise;
}
var fun2 = function (data) {
var deferred = Q.defer();
deferred.resolve(data+" fun2");
return deferred.promise;
}
var fun3 = function (data) {
var deferred = Q.defer();
deferred.resolve(data+" fun3");
return deferred.promise;
}
Q.all([
fun2("test1"),fun3("test2"),fun4("test3")
]).spread(function(){
console.log(arguments);//獲得的參數(shù)為('test1 fun1', 'test2 fun2', 'test3 fun3' )
});