Js单线程
- 同步模式:程序的执行顺序与任务的排列顺序一致。一次只能完成一件任务,如果有多个任务,就必须排队,前面一个任务完成,后面一个任务才能执行。
- 异步模式:程序的执行顺序与任务的排列顺序不一致。前一个任务结束后执行回调函数,后一个任务不等前一个任务结束就执行。
js的执行环境是单线程的,也就是同步执行模式,因为只有这样,js才能更好的与浏览器交互。假如js是多线程的,在浏览器中同时操作一个DOM,一个线程要求添加节点,另一个线程要求删除节点,这时浏览器就不知道以哪个线程为准。为了避免此类问题,降低复杂度,js选择只用一个主线程来执行代码,来保证程序执行的一致性。
js单线程的弊端是,当某个任务耗时长时,后面的任务必须排队等着,常常会出现浏览器无响应等情况。因此,耗时长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax。 js实现异步有如下方案:
1. 回调函数
函数B作为参数传递到函数A里,A执行完异步操作后再执行B,B是A的回调函数。
缺点:高耦合,维护困难,流程混乱,回调地狱,每个任务只能指定一个回调函数。
注意:回调并不一定就是异步,回调也可以是同步
1 | function getInfo(callback) { |
1 | function getInfo(callback) { |
2. 事件监听
采用事件驱动模式,任务的执行取决于某个事件是否发生。可绑定多个事件,每个事件可指定多个回调函数。可看作是发布订阅模式的一个简化版本。
缺点:整个程序都要变成事件驱动型,运行流程不清晰。
1 | f1.addEventListener('done',f2); // 绑定事件,'done'事件一旦被触发便执行f2 |
3. 发布/订阅模式
信号中心发布信号,其他事件订阅信号,订阅者收到信号后开始执行。
与事件监听类似,但明显更优。可查看消息中心,了解存在多少信号、每个信号有多少订阅者,从而监控程序运行。
1 | //这里使用了一款JQuery插件 |
4. Promise 异步处理(ES6)
一种异步编程解决方案,相比传统回调函数更加合理和优雅,采用了链式编程,将异步对象和回调函数脱离开来,解决多层回调地狱的问题。
promise对象三种状态:pending
等待中, fulfilled
和 rejected
promise构造函数接收两个函数作为参数:resolve
,reject
只有异步操作的结果,可以决定promise对象的状态。
1 | var p = new Promise((resolve, reject) { |
5. Generator 异步处理 (ES6)
封装了多个内部状态状态机,通过调用next()
方法,使指针移向下一个状态。
缺点:必须依靠执行器next()来执行。
1 | function * generator() { |
6. async: generator语法糖(ES8)
更好的语义,进一步优化promise的链式调用写法,用同步的方式写异步。
内置执行器,再也不用next()了,被认为是异步编程的终极解决方案。
但async并不会取代promise,底层仍然是promise。
1 | function p = new Promise(){...}; |