一、了解什么是同步什么是异步
同步:代码从上往下执行,如果前面的代码执行得比较慢,后面的代码就一直在等待
异步:针对一些比较耗时的异步API,js不会同步执行它们,而是异步,比如定时器以及事件处理函数
二、了解执行流程
1、 浏览器是多线程
2、 js引擎是单线程
先执行同步代码,发现异步代码调入新的区域执行,完成后进入回调队列中排队等候,当同步代码执行完成后会再去执行回调队列的代码
event loop + callback queue
举例:
三、异步函数不能立即获得执行结果
在同步中可以获取到return的123
下面我们使用异步代码
因为执行完console.log再执行异步函数里面的代码,所以输出结果是undefined
四、解决异步函数不能立即获得执行结果
五、回调地狱的产生
在异步函数中,函数的输出结果是这样的:
如果要保证输出顺序是1 2 3,我们需要改造代码:
如果嵌套的层级多了,就会产生回调地狱的问题
解决回调地狱的方法有很多
六、解决回调地狱的方法一:promise
虽然代码看起来比回调地狱清晰一点,但感觉和回调第一没什么区别,最后还是要通过嵌套的方法输出,所以我们对代码进行进一步的改造:
七、解决回调地狱的第二种方法:generator
先来了解一下generator函数和普通函数有什么区别:
普通函数如果有return,外面就能拿到return后面的值,普通函数如果没有return,外面的值就是undefined,而且只要有了return,就会阻止代码继续向下执行。我们可以在普通函数的前面加上*就变成了generator生成器函数,普通函数只能返回一次值,generator可以返回多次值,generator使用yield来返回值,普通函数使用return返回值
使用generator方法改造前面的函数:
但这样代码量看起来太多了,我们使用第三方插件co来简化代码量:
但是使用co会产生一个问题,虽然输出顺序是正确的,但是输出时间与前面的不一样了。比如这个代码,他是隔9秒(js不能保证时间一定是正确的)后同时输出1 2 3,前面的代码是3秒输出1,9秒后输出2 3
八、解决回调地狱的第三种方法:async await
这个方法和调用co一样有时间的问题
九、宏任务和微任务
我们一般把执行每一小块代码称之为任务
宏任务:主线程中的同步代码,定时器,事件函数
微任务:promise, generator, async await
主线程的一个宏任务执行完会检查是否有微任务,有会执行完微任务再开启一个宏任务