1.什么是异步
- 异步(async)是相对于同步(sync)而言的
- 同步就是一件事一件事的执行。只有前一个任务执行完毕,才能执行后一个任务。而异步就比如
```js
console.log(1)
setTimeout(function(){
console.log(2)
},100)
console.log(3)
//这里打印顺序是 1 3 2
```
- setTimeout就是一个异步任务,当JS引擎顺序执行到setTimeout的时候发现他是个异步任务,则会把这个任务挂起,继续执行后面的代码。
- 那么为什么要使用异步呢?
由于javascript是单线程的,只能在JS引擎的主线程上运行的,所以js代码只能一行一行的执行,不能在同一时间执行多个js代码任务,这就导致如果有一段耗时较长的计算,比如ajax请求等IO操作,如果没有异步的存在,就会出现用户长时间等待
所以我们认为异步,就比如我们请求服务端的数据,我们发送完请求后就继续执行下面的代码,把发送请求加入到异步队列中,当服务端处理完数据后返回结果,异步队列通知我们,我们在进行数据处理,这样的话,数据处理就可以相互不影响,多条线齐头并进。什么是异步**
- 异步(async)是相对于同步(sync)而言的
- 同步就是一件事一件事的执行。只有前一个任务执行完毕,才能执行后一个任务。而异步就比如
```js
console.log(1)
setTimeout(function(){
console.log(2)
},100)
console.log(3)
//这里打印顺序是 1 3 2
```
- setTimeout就是一个异步任务,当JS引擎顺序执行到setTimeout的时候发现他是个异步任务,则会把这个任务挂起,继续执行后面的代码。
- 那么为什么要使用异步呢?
由于javascript是单线程的,只能在JS引擎的主线程上运行的,所以js代码只能一行一行的执行,不能在同一时间执行多个js代码任务,这就导致如果有一段耗时较长的计算,比如ajax请求等IO操作,如果没有异步的存在,就会出现用户长时间等待
所以我们认为异步,就比如我们请求服务端的数据,我们发送完请求后就继续执行下面的代码,把发送请求加入到异步队列中,当服务端处理完数据后返回结果,异步队列通知我们,我们在进行数据处理,这样的话,数据处理就可以相互不影响,多条线齐头并进。
2.ES5怎么处理异步呢?
- **回调函数**
回调是一个函数被作为一个参数传递到另一个函数里,在那个函数执行完后再执行。( 也即:B函数被作为参数传递到A函数里,在A函数执行完后再执行B )
假设 有两个函数 f1和f2 后者等待前者的执行结果。
```js
function f1(callback){
  setTimeout(function () {
    // f1的任务代码
    callback();
  }, 1000);
}
// 执行
f1(f2)
```
采用这种方式,我们把同步操作变成了异步操作,f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。
- **事件监听的方式**
- 采用事件驱动模式。
- 任务的执行不取决代码的顺序,而取决于某一个事件是否发生。
- 这样的话比较容易理解,可以绑定多个事件,每一个事件可以指定回调函数,事件触发函数执行
- 监听函数有:on,bind,listen,addEventListener,observe
- 比如addEventListener方法
```html
<div id="id1">
<div id="id2"></div>
</div>
```
- js代码
```js
id1.addEventListener("click",function(){console.log('id1');},false);
id2.addEventListener("click",function(){console.log('id2');},false);
//点击id=id2的div,先在sonsole中输出,先输出id2,在输出id1
id1.addEventListener("click",function(){console.log('id1');},false);
id2.addEventListener("click",function(){console.log('id2');},true);
//点击id=id2的div,先在sonsole中国输出,先输出id1,在输出id2
```
- **发布订阅的方式**
- 我们假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。
我们采用的是Ben Alman的Tiny Pub/Sub,这是jQuery的一个插件演示一下
```js
// f2向"信号中心"jQuery订阅"done"信号。
jQuery.subscribe("done", f2);
function f1(){
  setTimeout(function () {
    // f1的任务代码
    jQuery.publish("done");
  }, 1000);
}
// f1执行完,发布信号,f2收到信号后,执行即可
3.ES5异步处理有什么问题?
- 回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之
间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。
- 事件监听的方式优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函
数,而且可以“去耦合”(Decoupling),有利于实现模块化。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。
- 这种方法的性质与”事件监听”类似,但是明显优于后者。因为我们可以通过查看”消息中心
”,了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。