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

推荐订阅源

Google DeepMind News
Google DeepMind News
Stack Overflow Blog
Stack Overflow Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
N
Netflix TechBlog - Medium
腾讯CDC
C
Check Point Blog
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
S
SegmentFault 最新的问题
F
Fortinet All Blogs
美团技术团队
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
F
Full Disclosure
Recorded Future
Recorded Future
D
DataBreaches.Net
博客园 - 【当耐特】
Martin Fowler
Martin Fowler
J
Java Code Geeks
I
InfoQ
Y
Y Combinator Blog
A
About on SuperTechFans
AI
AI
爱范儿
爱范儿
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Forbes - Security
Forbes - Security
W
WeLiveSecurity
M
MIT News - Artificial intelligence
雷峰网
雷峰网
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Docker
Recent Commits to openclaw:main
Recent Commits to openclaw:main
量子位
V2EX - 技术
V2EX - 技术
Project Zero
Project Zero

博客园 - 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`

 相关资料: