惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Blog of Author Tim Ferriss
Know Your Adversary
Know Your Adversary
P
Palo Alto Networks Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
K
Kaspersky official blog
L
LINUX DO - 热门话题
P
Proofpoint News Feed
P
Privacy & Cybersecurity Law Blog
Google DeepMind News
Google DeepMind News
Attack and Defense Labs
Attack and Defense Labs
Cisco Talos Blog
Cisco Talos Blog
AI
AI
L
LINUX DO - 最新话题
H
Heimdal Security Blog
Hacker News: Ask HN
Hacker News: Ask HN
Webroot Blog
Webroot Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
The GitHub Blog
The GitHub Blog
I
Intezer
Blog — PlanetScale
Blog — PlanetScale
有赞技术团队
有赞技术团队
S
Securelist
博客园_首页
IT之家
IT之家
Schneier on Security
Schneier on Security
博客园 - 叶小钗
罗磊的独立博客
WordPress大学
WordPress大学
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
MongoDB | Blog
MongoDB | Blog
P
Proofpoint News Feed
阮一峰的网络日志
阮一峰的网络日志
A
Arctic Wolf
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
W
WeLiveSecurity
The Register - Security
The Register - Security
D
DataBreaches.Net
S
Security @ Cisco Blogs
Security Archives - TechRepublic
Security Archives - TechRepublic
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
腾讯CDC
Recorded Future
Recorded Future
NISL@THU
NISL@THU
N
News and Events Feed by Topic
T
Tailwind CSS Blog
N
News and Events Feed by Topic
Cyberwarzone
Cyberwarzone
T
Tor Project blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com

博客园 - smile轉角

【js】ES5,ES6继承是如何实现的 【面试题】思维逻辑方面 【js】js内置对象Error(错误机制) 【TS】学习笔记 【js】CommonJS、AMD、CMD三种规范 【其他】查看Animate.css官网动画没有效果 【vue3】父子组件通信之 vue3 defineProps,defineEmits ,defineExpose 【js】JS严格模式有什么特点 【css】使用弹性盒子布局时,省略号问题 【vue】 Failed to load resource: the server responded with a status of 404 (Not Found) 【第三方】富文本调研 【js】元素是否在可视区范围内 【js】json的相关操作 【vue3】资料 【css】展示背景图片的底部部分 【html】 svg 【html5】html5中input 标签 type值为range时,修改其默认css 【js】forEach,for...in,for...of 区别 【js】map,reduce,filter的区别
【js】setTimeout、Promise、Async/Await 的区别
smile轉角 · 2023-04-14 · via 博客园 - smile轉角

三者在事件循环中的是不同的,事件循环中分为宏任务队列和微任务队列

  • 其中setTimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行;
  • promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行;
  • async函数表示函数里面可能会有异步方法,await后面跟一个表达式,async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行

setTimeout

console.log('script start') //1. 打印 script start

setTimeout(function() {
    console.log('settimeout') // 4. 打印 settimeout
}) // 2. 调用 setTimeout 函数,并定义其完成后执行的回调函数

console.log('script end') //3. 打印 script start

// 输出顺序:
// ->script start
// ->script end
// ->settimeout

Promise

Promise本身是同步的立即执行函数,

当在executor中执行resolve或者reject的时候,

此时是异步操作,

会先执行then/catch等,

当主栈完成后,才会去调用resolve/reject中存放的方法执行,

打印p的时候,是打印的返回结果,一个Promise实例。

console.log('script start')
let promise1 = new Promise(function(resolve) {
    console.log('promise1')
    resolve()
    console.log('promise1 end')
}).then(function() {
    console.log('promise2')
})
setTimeout(function() {
    console.log('settimeout')
})
console.log('script end')

// 输出顺序: 
// ->script start
// ->promise1
// ->promise1 end
// ->script end
// ->promise2
// ->settimeout

当JS主线程执行到Promise对象时,

  • promise1. then() 的回调就是一个 task
  • promise1 是 resolved或rejected: 那这个 task 就会放入当前事件循环回合的 microtask queue
  • promise1 是 pending: 这个 task 就会放入 事件循环的未来的某个(可能下一个)回合的 microtask queue 中
  • setTimeout 的回调也是个 task ,它会被放入 macrotask queue 即使是 0ms 的情况

async/await

async 函数返回一个 Promise 对象,当函数执行的时候,
一旦遇到 await 就会先返回,
等到触发的异步操作完成,再执行函数体内后面的语句。
可以理解为,是让出了线程,跳出了 async 函数体。

async function async1() {
    console.log('async1 start');

    await async2();
    console.log('async1 end')

}
async function async2() {

    console.log('async2')

}

console.log('script start');
async1();
console.log('script end')

// 输出顺序:

// ->script start
// ->async1 start
// ->async2
// ->script end
// ->async1 end

 拓展:

// 面试题 
Promise.resolve().then(()=>{
    console.log('Promise1');
    setTimeout(()=>{
        console.log('setTimeout2')
    },0)
})
setTimeout(()=>{
    console.log('setTimeout1')
    Promise.resolve().then(()=>{
        console.log('Promise2')
    })
})
// Promise1 setTimeout1 Promise2 setTimeout2
let p = Promise.resolve().then(() => {
    console.log(p);
    const timer2 = setTimeout(() => {
        console.log('timer2')
    }, 0)
});
const timer1 = setTimeout(() => {
    console.log('timer1')
    Promise.resolve().then(() => {
        console.log('promise2')
    })
}, 0)
console.log('start');

代码运行步骤:
1、遇到Promise.resolve().then作为微任务,加入到微任务队列
2、timer1是宏任务,加入到宏任务队列
3、console.log同步代码,输出`start`,主线程中同步任务执行完。
4、微任务队列中有Promise.resolve().then,输出p,因为此时p没有resolve(),以及reject()终止掉,因此会输出`pending`。
4、timer2是宏任务,加入到宏任务队列,此时宏任务队列中有timer1、timer2。
5、微任务执行结束,进入到下一轮宏任务阶段。运行timer1,输出`timer1`,Promise.resolve().then是微任务。
6、宏任务结束,运行微任务,输出`promise2`。
7、微任务运行结束。此时宏任务队列中还有timer2,因此输出`timer2`

 相关资料: