async await,EventLoop事件循环,微任务和宏任务

01-async await语法

我们先来学习下语法

<script>
async function 函数名() {
    const result = await Promise对象
    // 拿到Promise对象内成功的结果继续向下执行
}
</script>

示例

写个小例子, 来使用下async+await

<script>
// 目标: 掌握下async和await语法
// 目的: 用await取代then函数, 来提取成功的值在原地
let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功的值')
    }, 2000)
})
​
// 普通函数: async+await
async function fn() {
    const result = await p
    console.log(result)
}
fn()
​
// 箭头函数: async+await
const myFn = async () => {
    const result = await p
    console.log(result)
}
myFn()
</script>

小结

  1. async和await的作用是什么?

  • 取代then函数, 来提取成功的结果

02.概念async和await注意事项

目标

了解async和await的注意事项

讲解

  1. 新建html文件, 来讲解如下注意事项

<script>
let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        // resolve(1)
        reject(new Error('失败'))
    }, 2000)
})
​
async function myFn() {
    try {
        const res = await p
        console.log(res);
    } catch (err) {
        console.error(err)
    }
}
myFn()
</script>

小结

  1. await后面的值都可以是什么?

  • 可以是Promise对象或者一个基础类型的值, 但常配合Promise对象使用, 提取其成功的结果

  1. await想要捕获Promise内失败结果怎么做?

  • 使用try和catch代码块进行捕获

03.概念_EventLoop事件循环

目标

理解EventLoop事件循环的概念

讲解

  1. 说明:JavaScript 是一门单线程执行的脚本语言。也就是说,同一时间只能做一件事情。

  2. 思考:单线程执行任务队列会有什么问题呢?    如果前一个任务非常耗时,则后续的任务就不得不一直等待。    为了防止某个耗时任务导致程序假死的问题,异步代码 由 js 委托给宿主环境(node环境, 浏览器)等待执行 JS引擎(c++写的代码)用来阅读+解析+执行, 我们编写的代码

  3. 然后异步任务代码执行后, 要执行的回调函数会在任务队列中排队等待

  4. 组成:

    • 执行栈(JS主线程/引擎)

    • 宿主环境

    • 任务队列

  5. 图示:

  6. 图示2:

  7. 阅读如下代码, 更好的理解事件循环

​
console.log(1);
const userName = '老李'
if (true) {
    console.log(2);
} else {
    console.log(3);
}
setTimeout(() => {
    console.log(4);
}, 1000)
function myFn() {
    console.log(5);
}
for (let i = 0; i < 3; i++) {
    console.log(6);
}
myFn()
setTimeout(() => {
    console.log(7);
}, 0)
const youFn = () => {
    console.log(8);
}
document.addEventListener('click', () => {
    console.log(9);
})
const obj = {
    name: '老刘'
}
youFn()
console.log(10);
  1. 事件循环的比较简单,它是一个在  "JavaScript 引擎等待任务","执行任务"和"进入休眠状态等待更多任务"这几个状态之间转换的无限循环。 引擎的一般算法:

    1. 当有任务时:

      • 从最先进入的任务开始执行。

    2. 没有其他任务,休眠直到出现任务,然后转到第 1 步。

  2. 任务队列 根据规范,事件循环是通过任务队列的机制来进行协调的。一个 Event Loop 中,可以有一个或者多个任务队列(task queue),一个任务队列便是一系列有序任务(task)的集合;每个任务都有一个任务源(task source),源自同一个任务源的 task 必须放到同一个任务队列,从不同源来的则被添加到不同队列。setTimeout/Promise 等API便是任务源。 在事件循环中,每进行一次循环的关键步骤如下:

    • 在此次循环中选择最先进入队列的任务(oldest task),如果有则执行(一次)

    • 检查是否存在 微任务(Microtasks),如果存在则不停地执行,直至清空 微任务队列(Microtasks Queue)

    • 更新 render(DOM渲染)

    • 以上为一次循环,主线程重复执行上述步骤

在上述循环的基础上需要了解几点:

  • JS分为同步任务和异步任务

  • 同步任务都在主线程上执行,形成一个执行栈

  • 主线程之外,宿主环境管理着一个任务队列,只要异步任务有了运行结果,就在任务队列之中放置一个事件。

  • 一旦执行栈中的所有同步任务执行完毕(此时JS引擎空闲),系统就会读取任务队列,将可运行的异步任务添加到可执行栈中,开始执行。

小结

  1. 什么是事件循环?

  • 主线程逐行执行代码, 遇到异步任务, 交给宿主环境执行, 执行完毕把要执行的回调函数推入任务队列, 等待主线程空闲的时候, 会调用任务队列中回调函数推入主线程执行栈执行, 执行后再次尝试清空任务队列里下一个回调函数, 这样不断清空和执行任务队列里回调函数的过程就叫事件循环

04.概念_微任务和宏任务

目标

  • 了解微任务宏任务的概念

  • 掌握微任务队列宏任务队列的执行时机

讲解

  1. 在上节课我们学到的事件循环中, 有一个任务队列, 任务队列可以细分为2个队列

    • 微任务队列

    • 宏任务队列

你也可以认为, 任务队列, 类似一个数组结构, 里面都是异步代码要放入执行栈执行的, 回调函数体

  1. 哪些是微任务代码, 哪些是宏任务代码呢?

微任务代码

宿主环境是JS引擎

任务(代码)微任务环境
Promise.then()微任务浏览器

宏任务代码

宿主环境是浏览器

任务(代码)宏任务环境
script宏任务浏览器
事件宏任务浏览器
网络请求(Ajax)宏任务浏览器
setTimeout() 定时器/setInterval() 多次定时器宏任务浏览器
  1. 重点注意

    • 异步任务的回调函数, 才会放入, 推入任务队列中, 等待被执行栈调用

    • 微任务在宏任务之前被执行(不包含最开始执行的script标签(宏任务))

  2. 阅读如下代码执行结果

​
console.log(1);
​
setTimeout(() => {
    console.log(2);
}, 0)
​
let p = new Promise((resolve, reject) => {
    resolve(3)
})
​
p.then(res => {
    console.log(res);
})
​
​
console.log(4);

小结

  1. 任务队列可以细分成哪2大类?

  • 宏任务队列和微任务队列

05.概念微任务和宏任务执行顺序

目标

  • 掌握同步任务, 微任务, 宏任务的执行顺序

讲解

  1. 先执行第一个宏任务(一般是script标签内/模块内)从头开始, 执行所有同步任务

  2. 中间遇到微任务和宏任务, 交给宿主环境, 然后有结果, 暂时把回调函数, 推入到相应任务队列中等待

  3. 同步代码执行完毕后, 尝试先清空当前微任务队列中所有回调函数, 一个个调入执行栈执行

  4. 然后再执行宏任务队列中的一个宏任务, 执行宏任务里所有同步代码, 回到步骤1的循环继续

图示:

  1. 阅读如下代码回答结果

console.log(1)
setTimeout(function() {
  console.log(2)
  new Promise(function(resolve) {
    console.log(3)
    resolve()
  }).then(function() {
    console.log(4)
  })
})
​
new Promise(function(resolve) {
  console.log(5)
  resolve()
}).then(function() {
  console.log(6)
})
setTimeout(function() {
  console.log(7)
  new Promise(function(resolve) {
    console.log(8)
    resolve()
  }).then(function() {
    console.log(9)
  })
})
console.log(10)

小结

  1. 微任务和宏任务以及同步代码是如何执行的?

  • 先执行第一个宏任务, 然后同步任务, 然后微任务, 然后下一个宏任务如此循环, 直到所有代码执行完毕

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值