1、什么是异步

简单来说就是遇到(网络请求,定时任务)不能卡住;

2、异步进化史

回调函数 —> Promise —> Generator —> async/await。

3、同步异步举例

  1. // 异步 (callback 回调函数)
  2. console.log(100)
  3. setTimeout(function(){
  4. console.log(200)
  5. },1000)
  6. console.log(300)
  7. //100
  8. //300
  9. //200
  10. // 同步
  11. console.log(100)
  12. alert(200)
  13. console.log(300)
  14. //100
  15. //200
  16. //300

4、异步应用场景

4.1 网络请求,如ajax图片加载

  1. // ajax
  2. console.log('start')
  3. $.get('./data1/json',function(data1){
  4. console.log(data1)
  5. })
  6. console.log('end')

4.2 定时任务,如setTimeout

  1. //图片加载
  2. console.log('start')
  3. let img = document.createElement('img')
  4. img.onload = function(){
  5. console.log('loaded')
  6. }
  7. img.src = '/xxx.png'
  8. console.log('end')

4.3 事件监听、绑定

  1. // 事件监听
  2. document.getElementById('#myDiv').addEventListener('click', function (e) {
  3. console.log('我被点击了')
  4. }, false);

5、回调地狱

当回调只有一层的时候感觉没有什么问题,但是一但嵌套层级过多,代码可读性和可维护性就变差。

  1. const https = require('https');
  2. https.get('目标接口1', (res) => {
  3. console.log(data)
  4. https.get('目标接口2', (res) => {
  5. https.get('目标接口3'), (res) => {
  6. console.log(data)
  7. https.get('目标接口4', (res) => {
  8. https.get('目标接口5', (res) => {
  9. console.log(data)
  10. .....
  11. // 无尽的回调
  12. }
  13. }
  14. }
  15. }
  16. })

6.典型题

6.1 同步与异步的区别

  • 基于JS是单线程语言
  • 异步不会阻塞代码执行
  • 同步会阻塞代码执行

6.2 异步加载图片

  1. function loadImg(src){
  2. return new promise(
  3. (resolve,reject)=>{
  4. const img = document.createElement('img')
  5. img.onload = () => {
  6. resolve(img)
  7. }
  8. img.onerror=() => {
  9. reject(new Error(`图片加载失败`))
  10. }
  11. img.src = src
  12. }
  13. )
  14. }
  15. const url1 = 'xxx'
  16. const url2 = 'xxx'
  17. loadImg(url).then(img=>{
  18. console.log(img1.width)
  19. return img1 //普通对象
  20. }).then(img1=>{
  21. console.log(img.height)
  22. return loadImg(url2) //promise实例
  23. }).then(img2=>{
  24. console.log(img2.height)
  25. }).catch(ex=>console.log(ex))

6.3 setTimeout场景题

  1. // setTimeout笔试题
  2. console.log(1)
  3. setTimeout(function(){
  4. console.log(2)
  5. },1000)
  6. console.log(3)
  7. setTimeout(funcion()=>{
  8. console.log(4)
  9. },0)
  10. console.log(5)
  11. //1 3 5 4 2

6.4 回调函数有什么缺点?如何解决回调地狱问题?

回调函数有一个致命的弱点,就是容易写出回调地狱(Callback hell)。假设多个请求存在依赖性,你可能就会写出如下代码:

  1. ajax(url, () => {
  2. // 处理逻辑
  3. ajax(url1, () => {
  4. // 处理逻辑
  5. ajax(url2, () => {
  6. // 处理逻辑
  7. })
  8. })
  9. })

回调地狱的根本问题就是:

  1. 嵌套函数存在耦合性,一旦有所改动,就会牵一发而动全身
  2. 嵌套函数一多,就很难处理错误

当然,回调函数还存在着别的几个缺点,比如不能使用 try catch 捕获错误,不能直接 return

解决方法:使用Promise;