我的博客: http://zhangsunyucong.topnode
这篇文章主要讲两个内容,一是,初步认识Promise,二是,Async模块和Async/Await的使用git
Promise表示一个异步操做的最终结果。一个Promise对象有一个then方法,then方法中返回一个Promise。github
- promise是一个包含了兼容promise规范then方法的对象或函数,
Promise有三种状态:pending, fulfilled 或 rejected。pending是等待执行状态,fulfilled是成功执行状态,rejected是失败执行状态。npm
Promise只能从pending到fulfilled或者从pending到rejected状态,当状态发生改变时,promise.then(onFulfilled, onRejected)方法将被调用。Promise可使用resolve或者reject将value或者reason做为下一个Promise的第一个回调参数。segmentfault
来个简单的Promise基本用法:数组
var promise = new Promise(function(resolve, reject){
//do something
if(success){
resolve(value);
} else {
reject(value);
}
});
promise.then(function(value){
//成功时调用
}, function(value){
//失败时调用
});
复制代码
上面的代码只是表示Promise用法的流程.promise
使用Promise/A+规范实现如下几个功能bash
- 上一步的结果能够做为下一步的参数
Promise的具体知识,能够参考这里异步
下面介绍Async模块和ES7的Async/Await的使用async
Async模块的github地址:github.com/caolan/asyn…
配置好node的环境后(具体过程,本身百度),安装Async模块
npm install --save async
Async模块提供了不少关于集合,流程控制,工具方法,这里只体验几个常见的流程控制方法:series,parallel,waterfall,auto。其余方法的用法,能够查看官方文档:文档地址
series(tasks, callback)
tasks能够是数组或者对象
series是串行执行tasks中的任务,若是有一个任务执行返回了错误信息,则再也不继续执行后面未执行的任务,并将结果以数组或者对象的形式传给callback。具体结果的格式由你定义tasks时使用的是数组仍是对象。
async.series([
function (callback) {
setTimeout(function () {
console.log("one");
callback(null, 'one');
}, 300);
},
function (callback) {
setTimeout(function () {
console.log("two");
callback(null, 'two');
}, 200);
},
function (callback) {
setTimeout(function () {
console.log("three");
callback(null, 'three');
}, 100);
}
], function (err, results) {
console.log(err);
console.log(results);
});
复制代码
运行结果:
one two three null [ 'one', 'two', 'three' ]
当tasks是对象:
async.series({
one: function (callback) {
setTimeout(function () {
console.log("one");
callback(null, 'one');
}, 300);
},
two: function (callback) {
setTimeout(function () {
console.log("two");
callback(null, 'two');
}, 200);
},
three: function (callback) {
setTimeout(function () {
console.log("three");
callback(null, 'three');
}, 100);
}
}, function (err, results) {
if(err) {
console.log("异常结束" + '结果为:' + results);
return;
}
console.log(results);
});
复制代码
运行结果:
one two three { one: 'one', two: 'two', three: 'three' }
上面代码中,从上到下的函数开始执行时间是逐渐减少的,而运行结果的输出顺序是one,two,three,说明series是串行执行任务的。
将第二个任务的代码改成如下的样子:
function (callback) {
console.log("two");
setTimeout(function () {
callback("errMsg", 'two');
}, 200);
}
复制代码
运行的结果为:
one two errMsg [ 'one', 'two' ]
能够看到,当第二个任务返回了错误信息,则不会再继续执行后面未执行的任务
parallel(tasks, callback)
tasks能够是一个数组或者对象
parallel是并行执行多个任务,若是有一个任务执行返回了一个错误信息,则再也不继续执行后面未执行的任务,并将结果以数组或者对象的形式传给callback。
async.parallel([
function (callback) {
setTimeout(function() {
console.log('one');
callback(null, 'one');
}, 500);
},
function (callback) {
setTimeout(function() {
console.log('two');
callback(null, 'two');
}, 200);
},
function (callback) {
setTimeout(function() {
console.log('three');
callback(null, 'three');
}, 100);
}
], function (err, results) {
console.log(err);
console.log(results);
});
复制代码
运行结果为:
three two one null [ 'one', 'two', 'three' ]
结果中的输出顺序是three,two,one,说明parallel是并行执行任务的。
一样,将第二个任务的代码改成:(数组定义tasks)
function (callback) {
setTimeout(function() {
console.log('two');
callback("errMsg", 'two');
}, 200);
},
复制代码
运行的结果为:
three two errMsg [ <1 empty item>, 'two', 'three' ] one
将第二个任务代码改成:(数组定义tasks)
function (callback) {
setTimeout(function() {
console.log('two');
callback("errMsg", 'two');
}, 200);
},
复制代码
将第三个任务代码改成:(数组定义tasks)
function (callback) {
setTimeout(function() {
console.log('three');
callback(null, 'three');
}, 200);
}
复制代码
也就是,第三个的开始执行时间改为和出现错误信息的第二个任务的时间同样。
运行的结果为:
two errMsg [ <1 empty item>, 'two' ] three one
从结果中能够看出,当前面执行的未完成的任务会占一个位置,然后面未完成的任务不会占数组的位置。
parallelLimit(tasks, limit, callback)
parallelLimit和parallel差很少,区别是它能够指定同时并行执行任务的最大数量。
async.parallelLimit({
one: function (callback) {
setTimeout(function() {
console.log('one');
callback(null, 'one');
}, 200);
},
two: function (callback) {
setTimeout(function() {
console.log('two');
callback(error, 'two');
}, 200);
},
three: function (callback) {
setTimeout(function() {
console.log('three');
callback(null, 'three');
}, 100);
}
}, 2, function (err, results) {
console.log(err);
console.log(results);
});
复制代码
运行的结果为:
one two errMsg { one: 'one', two: 'two' } three
若是是tasks是数组时,运行的结果是:
two errMsg [ <1 empty item>, 'two' ] one
因为同时并行执行任务的最大数量是2,因为第二个任务产生错误信息,第三个任务还没开始执行。另外若是要取最后回调结果中的值,对象定义tasks可能会更好。
waterfall(tasks, callback)
tasks只能是数组类型
waterfall会串行执行tasks中的任务,前一个任务的结果能够做为下一个任务的参数。
async.waterfall([
function (callback) {
console.log("one");
setTimeout(function() {
callback(null, 'one', 'two');
}, 200);
},
function (arg1, arg2, callback) {
console.log("two" + '参数:' + "arg1是" + arg1 + "arg2是" + arg2);
setTimeout(function() {
callback(null, 'three');
}, 200);
},
function (arg3, callback) {
console.log("three" + '参数:' + "arg3是" + arg3);
setTimeout(function() {
callback(null, 'done', 'done1');
}, 200);
}
], function (err, results) {
if(err) {
console.log("异常结束" + '结果为:' + results);
return;
}
console.log(results);
});
复制代码
运行的结果是:
one two参数:arg1是onearg2是two three参数:arg3是three done
输出的结果的顺序是one,two, three,是串行执行的。前一个任务的结果能够做为下一个任务的参数。
注意一下,代码中控制台输出的one,two,three代码是移到了定时器的外面。
auto(tasks, concurrencyopt, callback)
auto能够串行和并行执行任务,能够定义任务之间的依赖关系。没有依赖关系的任务会尽量快的开始并行执行,串行是因为任务的依赖关系而实现的。concurrencyopt指定的是并行执行任务的最大数量。tasks只能是对象类型。
async.auto({
task1: function(callback) {
setTimeout(function() {
console.log('task1');
callback(null, 'data', 'data1');
}, 200);
},
task2: function(callback) {
setTimeout(function () {
console.log('task2');
callback(null, 'data2');
}, 100)
},
task3: ['task1', 'task2', function(results, callback) {
console.log('task3', JSON.stringify(results));
setTimeout(function () {
console.log('task3');
callback(null, 'data3');
}, 200);
}],
task4: ['task3', function(results, callback) {
console.log('task4', JSON.stringify(results));
setTimeout(function () {
console.log('task4');
callback(null, {'task2':results.task2, 'task4':'data4'});
}, 100);
}]
}, function(err, results) {
console.log('err = ', err);
console.log('results = ', results);
});
复制代码
运行的结果是:
task2 task1 task3 {"task2":"data2","task1":["data","data1"]} task3 task4 {"task2":"data2","task1":["data","data1"],"task3":"data3"} task4 err = null results = { task2: 'data2', task1: [ 'data', 'data1' ], task3: 'data3', task4: { task2: 'data2', task4: 'data4' } }
task1和task2是不依赖于任何其余任务的,它们会尽量的开始,并且因为它们是并行执行的,task2的开始时间较短,因此task2比task1先开始。task3依赖于task1和task2,因此task3等到task1和task2执行完毕后再执行。task4依赖task3,因此task4要等到task3执行完毕后再执行。
主要看它们的用法
var task1 = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("result");
}, 1000);
});
};
var excTask1 = async function () {
console.log("start");
console.log(await task1());
console.log("end");
};
function awaitDemo() {
excTask1();
}
复制代码
连续点击运行四次,运行的结果为:
start start start start result end result end result end result end
async表明是一个async函数,await只能用在async函数中,await等待一个Promise的返回,直到Promise返回了才会继续执行await后面的代码。这里的Promise利用setTimeout模拟异步任务。
从输出结果中能够看出,每次执行都是到await时,就中止等待Promise的返回,后再继续执行await后面的代码。