版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/themagickeyjianan/article/details/88782062
1)背景
回调地狱在node.js中是一件让人头疼的事情,但是仔细想想:nodejs中多个异步任务之间的配合无非3种情况:
顺序执行: 后者使用前者的输入
顺序执行: 前后2者没啥关系(个人觉得这个没啥用,既然没关系就用并发的方式处理)
并发执行: 各个执行没有关系,需要同时执行
async库完美解决上面3个问题,虽然async有很多用法,但是主要解决上面3种,具体代码如下:
2)前者输出作为后者输入的顺序执行 async.waterfall
var async = require('async');
var fs = require('fs');
function main() {
console.time('start');
async.waterfall([
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, nextFileName) {
callback(err, nextFileName);
});
},
function (nextFileName, callback) {
fs.readFile(nextFileName, 'utf-8', function (err, data) { // 模拟错误,22.txt找不到
callback(err, data);
});
}
],
function (err, result) {
if (err) {
console.log('err =', err);
return;
}
console.log(result);
console.timeEnd('start');
}
);
}
main();
setTimeout(function () {
console.log('app end');
}, 7000);
输出:
$ node app3.js
abcdefg
start: 4.407ms
app end
可见,第一个任务读取完后才知道下一个文件读取什么,这样2个任务有前后依赖关系
当有一个任务出错时
var async = require('async');
var fs = require('fs');
function main() {
console.time('start');
async.waterfall([
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, nextFileName) {
callback(err, nextFileName);
});
},
function (nextFileName, callback) {
fs.readFile('222.txt', 'utf-8', function (err, data) { // 模拟错误,22.txt找不到
callback(err, data);
});
}
],
function (err, result) {
if (err) {
console.log('err =', err);
return;
}
console.log(result);
console.timeEnd('start');
}
);
}
输出:
$ node app3.js
err = { Error: ENOENT: no such file or directory, open 'E:\coding_now\NodeDemos\18-async\222.txt'
at Error (native)
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'E:\\coding_now\\NodeDemos\\18-async\\222.txt' }
app end
可见同样所有成功才算成功
3)各个异步任务无依赖的顺序执行(感觉这个没啥用) aysnc.series
var async = require('async');
var fs = require('fs');
function main() {
async.series([
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, data) {
callback(err, data);
});
},
function (callback) {
fs.readFile('./data/2.txt', 'utf-8', function (err, data) {
callback(err, data);
});
},
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, data) {
callback(err, data); // 模拟错误
});
},
function (callback) {
fs.readFile('./data/2.txt', 'utf-8', function (err, data) {
callback(err, data);
});
}
],
function (err, results) {
if(err){
console.log('err =', err);
return;
}
console.log(results);
}
);
}
main();
在4个任务都成功执行的情况下,输出
$ node app.js
[ '1234567', 'abcdefg', '1234567', 'abcdefg' ]
考虑出错情况(读取不存在的文件)
var async = require('async');
var fs = require('fs');
function main() {
async.series([
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, data) {
callback(err, data);
});
},
function (callback) {
fs.readFile('./data/22.txt', 'utf-8', function (err, data) { // 模拟错误,22.txt找不到
callback(err, data);
});
},
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, data) {
callback(err, data);
});
},
function (callback) {
fs.readFile('./data/2.txt', 'utf-8', function (err, data) {
callback(err, data);
});
}
],
function (err, results) {
if(err){
console.log('err =', err);
return;
}
console.log(results);
}
);
}
main();
那么4个任务都将失败:
$ node app.js
err = { Error: ENOENT: no such file or directory, open 'E:\coding_now\NodeDemos\18-async\data\22.txt'
at Error (native)
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'E:\\coding_now\\NodeDemos\\18-async\\data\\22.txt' }
4)并发执行 async.parallel
var async = require('async');
var fs = require('fs');
function main() {
console.time('start');
async.parallel([
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, data) {
callback(err, data);
});
},
function (callback) {
fs.readFile('./data/2.txt', 'utf-8', function (err, data) { // 模拟错误,22.txt找不到
setTimeout(function () {
callback(err, data);
}, 3000);
});
},
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, data) {
callback(err, data);
});
},
function (callback) {
fs.readFile('./data/2.txt', 'utf-8', function (err, data) { // 模拟错误,22.txt找不到
setTimeout(function () {
callback(err, data);
}, 3000);
});
}
],
function (err, results) {
if(err){
console.log('err =', err);
return;
}
console.log(results);
console.timeEnd('start');
}
);
}
main();
结果:
[ '1234567', 'abcdefg', '1234567', 'abcdefg' ]
start: 3007.267ms
如果是前面那个series
var async = require('async');
var fs = require('fs');
function main() {
console.time('start');
async.series([
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, data) {
callback(err, data);
});
},
function (callback) {
fs.readFile('./data/2.txt', 'utf-8', function (err, data) { // 模拟错误,22.txt找不到
setTimeout(function () {
callback(err, data);
}, 3000);
});
},
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, data) {
callback(err, data);
});
},
function (callback) {
fs.readFile('./data/2.txt', 'utf-8', function (err, data) { // 模拟错误,22.txt找不到
setTimeout(function () {
callback(err, data);
}, 3000);
});
}
],
function (err, results) {
if(err){
console.log('err =', err);
return;
}
console.log(results);
console.timeEnd('start');
}
);
}
main();
结果:
$ node app.js
[ '1234567', 'abcdefg', '1234567', 'abcdefg' ]
start: 6024.365ms
说明:parallel是并发执行的
有错误的情况(如文件不存在)
var async = require('async');
var fs = require('fs');
function main() {
console.time('start');
async.parallel([
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, data) {
callback(err, data);
});
},
function (callback) {
fs.readFile('./data/22.txt', 'utf-8', function (err, data) { // 模拟错误,22.txt找不到
setTimeout(function () {
callback(err, data);
}, 3000);
});
},
function (callback) {
fs.readFile('./data/1.txt', 'utf-8', function (err, data) {
callback(err, data);
});
},
function (callback) {
fs.readFile('./data/2.txt', 'utf-8', function (err, data) {
setTimeout(function () {
callback(err, data);
}, 3000);
});
}
],
function (err, results) {
if(err){
console.log('err =', err);
return;
}
console.log(results);
console.timeEnd('start');
}
);
}
main();
结果:
$ node app.js
err = { Error: ENOENT: no such file or directory, open 'E:\coding_now\NodeDemos\18-async\data\22.txt'
at Error (native)
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'E:\\coding_now\\NodeDemos\\18-async\\data\\22.txt' }