• 作者:老汪软件技巧
  • 发表时间:2024-08-28 11:02
  • 浏览量:

事件循环

JavaScript 的事件循环(Event Loop)是 JavaScript 运行时环境(如浏览器和 Node.js)用来处理异步代码和回调的一种机制。它允许 JavaScript 在执行长时间运行的操作(如 I/O、网络请求等)时不会阻塞用户界面或程序的其余部分。

事件循环的基本工作原理调用栈(Call Stack) :JavaScript 代码执行时,会按照调用顺序将函数放入调用栈中。当函数执行完毕,它会被从栈中移除。Web APIs:浏览器提供了一系列的 Web APIs,如setTimeout,fetch,XMLHttpRequest等,用于执行异步操作。这些 API 通常在“后台”线程中运行,以避免阻塞主线程。任务队列(Task Queue) :当异步操作完成时,相应的回调函数会被添加到任务队列中。这个队列是先进先出(FIFO)的。事件循环:当调用栈为空时,事件循环会从任务队列中取出任务,并将它们放入调用栈中执行。这个过程会不断重复,形成事件循环。微任务队列(Microtask Queue) :除了任务队列外,JavaScript 还有一个微任务队列。微任务队列的优先级高于任务队列。在每次事件循环迭代结束时,JavaScript 引擎会先处理所有微任务队列中的任务,然后再处理任务队列中的任务。JavaScript可以大致分为同步任务和异步任务同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行同步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等

异步任务又分为宏任务与微任务一般先执行宏任务再执行任务(先宏后微)

宏任务script(可以理解为外层同步代码)setTimeout/setintervalUI rendering/UI事件postMessage、MessageChannelsetlmmediate、I/O、(Node.js)微任务Promise.thenMutaionObserverObject.observe(已废弃;Proxy对象)process.nextTick(Node.js)

console.log(1);
setTimeout(()=>{
    console.log(2);
},0)
new Promise((resolve,reject)=>{
    console.log('new Promise');
    resolve()
}).then(()=>{
    console.log('then');
})
console.log(3);
 /**
输出
1
new Promise
3
then
2
解析:
1、经过 console.log(1); 所以打印   '1'
2、定时器属于新的宏任务,等待上一个宏任务和微任务执行完后才会执行
3、new Promise 直接执行  所以打印  '  new Promise   '
4、.then 属于微任务,放入微任务队列,等待宏任务执行完后再执行
5、经过 console.log(3); 所以打印   '3'
6、执行玩宏任务=>执行微任务(即执行打印 'then')
7、当第一次的宏任务和微任务执行完后执行下一次任务即执行定时器 打印  '2'
**/
        

async与 await

async和await是 JavaScript(ES2017 引入)中用于处理异步操作的关键字,它们让异步代码的编写和阅读变得更加直观和简单。在使用这些关键字之前,处理异步操作通常涉及到回调函数、Promises 或者生成器(Generators)。

_【JavaScript基础知识】--事件循环(同步任务、异步任务、宏任务、微任务)_【JavaScript基础知识】--事件循环(同步任务、异步任务、宏任务、微任务)

asyncawait

async函数返回一个promise对象,下面的两种方法是等效的

function Fn(){
    return Promise.resolve('TEST');
}
async function asyncFn() {
    return 'TEST'
}

正常情况下,await命令后是一个Promise对象,返回该对象的结果。如果不是 Promise对象,就直接返回对应的值

async function fff() {
    return await 123
}
fff().then(v => console.log(v))

不管await后面跟着的是什么,await都会阻塞后面的代码


async function awiatfn1() {
    console.log(1);
    await fn2()
    console.log(2); //阻塞 属于微任务等待宏任务执行完再执行
}
async function awaitfn2() {
    console.log('fn2');
}
awiatfn1()
console.log(3);
 /*
输出
1
fn2
3
2
*/

综合流程分析案例

async function  asyncfn1() {        //宏任务
    console.log('async1 start');   
    await asyncfn2()             
    console.log('async1 end');    //阻塞(后面执行) 属于微任务
}
async function asyncfn2() {       //宏任务
    console.log('async2');
}
console.log('script start');      //宏任务      
setTimeout(function(){
    console.log('setTimeout');   //定时器下一个宏任务
})
asyncfn1()
new Promise(function (resolve){      //宏任务
    console.log('promise1');
    resolve()
}).then(function(){
    console.log('promise2');    //阻塞(后面执行)  属于微任务
})
console.log('script end');        //宏任务
/*输出
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
解析:
先执行宏任务再执行微任务
1、先后执行的宏任务
console.log('script start');=>asyncfn1();=>asyncfn2()=>new Promise=>console.log('script end');
2、先后执行的微任务
console.log('async1 end');=>console.log('promise2');
3、下一个宏任务 
console.log('setTimeout'); 
*/