事件循环、宏任务、微任务、Promise

JavaScript 中的事件循环是一种处理异步操作的机制,它允许执行任务而不会阻塞主线程。

主要组成部分:

  1. 调用栈(Call Stack):用于存储执行上下文(函数调用)的栈结构。当函数被调用时,会创建一个执行上下文并被推入调用栈,当函数执行完毕时,其执行上下文会从栈中弹出。

  2. 消息队列(Message Queue):用于存储待执行的消息(任务)。每个消息都与一个函数相关联,当满足执行条件时,消息会被推入消息队列中。

  3. 事件循环(Event Loop):负责检查调用栈和消息队列的状态,当调用栈为空时,会从消息队列中取出消息并推入调用栈,以便执行相关的函数。这个过程是持续不断的,所以被称为“循环”。

  4. 微任务队列(Microtask Queue):用于存储微任务,微任务通常包括 Promise 的回调函数、MutationObserver 的回调函数等。微任务队列具有更高的优先级,会在每个宏任务执行完毕后立即执行。

事件循环步骤

  1. 执行当前调用栈中的任务,直到调用栈为空。
  2. 检查微任务队列,依次执行所有微任务,直到微任务队列为空。
  3. 如果存在宏任务,从消息队列中取出一个宏任务并推入调用栈,执行宏任务中的任务。
  4. 返回第一步。

宏任务(macrotasks)

 1.setTimeout 和 setInterval:定时器,指定一段时间后执行回调函数或者周期性地执行回调函数。

setTimeout(function() {
    console.log('This is a setTimeout callback');
}, 1000);

2.DOM 事件:例如点击事件、鼠标移动事件等,当用户与页面交互时触发。

document.addEventListener('click', function() {
    console.log('This is a click event');
});

3.XHR 请求:发送网络请求并在获取响应后执行回调函数。

var xhr = new XMLHttpRequest();
xhr.open('GET', 'url');
xhr.onload = function() {
    console.log('XHR request completed');
};
xhr.send();

4.I/O 操作:例如文件读取、写入等操作,通常是异步的,会被作为宏任务执行。

fs.readFile('file.txt', 'utf8', function(err, data) {
    if (err) throw err;
    console.log('File content:', data);
});

5.requestAnimationFrame:用于在下次重绘之前安排一次回调,通常用于执行动画效果。

微任务(microtasks)

1.Promise 的 then 方法:在 Promise 对象状态改变时执行对应的回调函数。

var promise = new Promise(function(resolve, reject) {
    resolve('This is a resolved promise');
});

promise.then(function(value) {
    console.log(value);
});

2.MutationObserver 的回调函数:监视 DOM 节点的变化并执行相应的操作。

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        console.log('DOM mutation observed');
    });
});

observer.observe(document.body, { attributes: true, childList: true, subtree: true });

3.Object.observe 的回调函数:监视 JavaScript 对象的变化并执行相应的操作。

var obj = { name: 'John', age: 30 };

Object.observe(obj, function(changes) {
    changes.forEach(function(change) {
        console.log('Object change observed:', change);
    });
});

obj.name = 'Jane'; // Triggers microtask

4.process.nextTick:在 Node.js 中将回调函数推入微任务队列,以便在事件循环的下一个阶段执行。

process.nextTick(function() {
    console.log('This is a process.nextTick callback');
});

5.async/await:在JavaScript中,async 函数允许使用 await 关键字来暂停和等待一个 Promise。但是,需要注意的是,await 只能用在 async 函数内部,并且它等待的是一个 Promise。非 Promise 类型的值(如普通函数调用或者 console.log)被 await 时,会立即执行,并返回该值(在这种情况下是一个 undefined,因为 console.log 不返回任何值)。

Promise输出顺序

        async function async1() {
            console.log('async1 start')//同步代码2
            await async2()//同步代码3
            console.log('async1 end')//*****微任务7****
        }
        async function async2() {
            console.log('async2')
        }
        console.log('script start')//同步代码1
        setTimeout(function () {
            console.log('settimeout')
        })                        //宏任务9
        async1()
        const promise1=new Promise(function (resolve) {
            console.log('promise1')//同步代码4
            resolve('sucess')//改变状态
            console.log('after')//同步代码5

        })
        promise1.then(function () {
            console.log('promise2')//微任务8 
            // console.log(promise1)//Promise {<fulfilled>: 'sucess'}
        })//.then只有在改变状态后才执行
        console.log('script end')//同步代码6

Promise.resolve(1)
.then(2)//数字
.then(Promise.resolve(3))//对象
.then(console.log("4"))
.then()
.then(console.log)//透传,将resolve(1) 的值直接传到最后一个then里
//4  1

.then 或者 .catch 的参数期望是函数,传入非函数则会发生值透传。

  new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('sucess')
        },1000)
        reject('rejected')
    }).then(rs=>console.log(rs))
    .catch(er=>console.log(er))
    .then(rs=>console.log(rs))
    .catch(er=>console.log(er))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值