所谓的异步指的是函数的调用并不直接返回执行的结果,而往往是通过回调函数异步的执行。异步的主要目的是处理非阻塞,在和HTML交互的过程中,会需要一些IO操作(典型的就是Ajax请求,脚本文件加载),如果这些操作是同步的,就会阻塞其它操作,用户的体验就是页面失去了响应。avascript通过事件驱动机制,在单线程模型下,以异步回调函数的形式来实现非阻塞的IO操作。
常见的异步模型
- 高阶函数
事件监听
1
2
3
4
5
6f.on("evt", g);
function f(){
setTimeout(function(){
f.trigger("evt");
})
}发布/订阅
1
2
3
4
5
6
7E.subscribe("evt", g);
function f(){
setTimeout(function () {
// f的任务代码
E.publish("evt");
}, 1000);
}Promise
Promise
传统的回调函数写法使得代码混成一团,变得横向发展而不是向下发展。Promises规范就是为了解决这个问题而提出的,目标是使用正常的程序流程(同步),来处理异步操作。
Promise把类似的异步处理对象和处理规则进行规范化, 并按照采用统一的接口来编写,采取规定方法之外的写法都会出错。promise的功能是可以将复杂的异步处理轻松地进行模式化。
简单来说,它起到代理作用(proxy),充当异步操作与回调函数之间的中介。它使得异步操作具备同步操作的接口,使得程序具备正常的同步运行的流程,回调函数不必再一层层嵌套。它的思想是,每一个异步任务立刻返回一个Promise对象,由于是立刻返回,所以可以采用同步操作的流程。这个Promises对象有一个then方法,允许指定回调函数,在异步任务完成后调用。
ECMAScript 6将其写入语言标准,因此目前JavaScript语言原生支持Promise对象。
更多Promise操作-Promise
异步操作的流程控制
1、串行执行
可以编写一个流程控制函数,让它来控制异步任务,一个任务完成以后,再执行另一个。这就叫串行执行
1 | var items = [ 1, 2, 3, 4, 5, 6 ]; |
函数series就是串行函数,它会依次执行异步任务,所有任务都完成后,才会执行final函数。items数组保存每一个异步任务的参数,results数组保存每一个异步任务的运行结果
2、并行执行1
2
3
4
5
6
7
8
9
10
11var items = [ 1, 2, 3, 4, 5, 6 ];
var results = [];
items.forEach(function(item) {
async(item, function(result){
results.push(result);
if(results.length == items.length) {
final(results);
}
})
});
上面代码中,forEach方法会同时发起6个异步任务,等到它们全部完成以后,才会执行final函数。
并行执行的好处是效率较高,比起串行执行一次只能执行一个任务,较为节约时间。但是问题在于如果并行的任务较多,很容易耗尽系统资源,拖慢运行速度。因此有了第三种流程控制方式
3、并行与串行的结合
所谓并行与串行的结合,就是设置一个门槛,每次最多只能并行执行n个异步任务。这样就避免了过分占用系统资源。
1 | var items = [ 1, 2, 3, 4, 5, 6 ]; |
JavaScript 多线程
JavaScript 中的 Worker 对象可以创建一个独立线程来处理数据,很自然的处理了阻塞问题。我们可以把繁重的计算任务交给 Worker,等他处理完了再把数据 Post 过来。
Worker 是一个有用的工具,可以创建 ajax 对象和 WebSocket 对象,也就是说他可以直接向服务器请求数据。不过他不能访问 DOM 的信息,更不能直接处理 DOM。
更多的worker-worker
Generator 对象解决异步
参考:https://segmentfault.com/a/1190000002545312
http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html