js执行顺序问题

在实践中才慢慢明白了js执行顺序问题
遵循事件循环机制,当JS解析执行时,会被引擎分为两类任务,同步任务(synchronous) 和 异步任务(asynchronous)。对于同步任务来说,会被推到执行栈按顺序去执行这些任务。对于异步任务来说,当其可以被执行时,会被放到一个 任务队列(task queue) 里等待JS引擎去执行。当执行栈中的所有同步任务完成后,JS引擎才会去任务队列里查看是否有任务存在,并将任务放到执行栈中去执行,执行完了又会去任务队列里查看是否有已经可以执行的任务。这种循环检查的机制,就叫做事件循环(Event Loop)。对于任务队列,其实是有更细的分类。其被分为 微任务(microtask)队列 & 宏任务(macrotask)队列。
宏任务包括:整体代码(script) ✅ ✅
UI交互事件 ✅ ❌
I/O ✅ ✅
setTimeout ✅ ✅
setInterval ✅ ✅
setImmediate ❌ ✅
requestAnimationFrame
微任务包括:
process.nextTick ❌ ✅ process.nextTick > promise.then **
MutationObserver ✅ ❌
Promise.then catch finally
事件循环的具体流程如下:
从宏任务队列中,按照入队顺序,找到第一个执行的宏任务,放入调用栈,开始执行;
执行完该宏任务下所有同步任务后,即调用栈清空后,该宏任务被推出宏任务队列,然后微任务队列开始按照入队顺序,依次执行其中的微任务,直至微任务队列清空为止;
当微任务队列清空后,一个事件循环结束;
接着从宏任务队列中,找到下一个执行的宏任务,开始第二个事件循环,直至宏任务队列清空为止。
这里有几个重点:
当我们第一次执行的时候,解释器会将整体代码script放入宏任务队列中,因此事件循环是从第一个宏任务开始的;
如果在执行微任务的过程中,产生新的微任务添加到微任务队列中,也需要一起清空;微任务队列没清空之前,是不会执行下一个宏任务的。
在补充一个页面渲染的机制是同事件循环机制的(也就是在下一个宏任务开始之前会进行一次渲染)

在这里插入代码片async function async1() {
		    console.log("a");
		    const res = await async2();//此处会阻塞代码,不会直接执行b 此处res并没有值
			// 注解:
			//ajax请求也是同样的 可以通过使用await来控制执行顺序,async使用的话返回的对象是promise才有效
			
			//await后面的函数会先执行一遍,然后就会跳出整个async函数来执行后面js栈的代码,等本轮事件循环执行完(就是同步任务执行完)了之后又会跳回到async函数中等待await后面表达式的返回值,
			//如果返回值为非promise则继续执行async函数后面的代码,否则将返回的promise放入promise队列。
		    console.log("b");
		}
		
		async function async2() {
		    console.log("c");
		    return 2;
		}
		
		console.log("d");
		
		setTimeout(() => {
		    console.log("e");
			//setTimeout(fn,0)这样的代码,0秒后执行又是什么意思呢?是不是可以立即执行呢?
			
			//答案是不会的,setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,意思就是不用再等多少秒了,
			//只要主线程执行栈内的同步任务全部执行完成,栈为空就马上执行
		}, 0);
		
		async1().then(res => {
		    console.log("f")
		})
		
		new Promise((resolve) => {
		    console.log("g");
		    resolve();
		}).then(() => {
		    console.log("h");
		});
		
		console.log("i");

最后附上执行顺序
执行顺序问题:
先从script进入宏任务 d a c g i (c之后不会立马输出b)
然后阻塞任务完成 接下来输出 b
然后进入微任务 promise.then() f h 微任务清空
第一个事件循环执行完
进入第二个宏任务 setTimeout 输出e

last but not least
在应对ajax想要进行同步操作的可以有三种实现方法
前提 fn1()执行完拿到某些值才执行fn2()和fn3()
方法一:就是函数嵌套 fn1()回调成功之后,在调用f2()和f3()
方法二:
使用promise.then()通过上边的实例我们得出then是要比promise的函数后执行
方法三:
使用async/await方法
await fn1()
fn2();
fn3();
对于方法二和三都要稍微改造一下函数变成promise返回值的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值