js事件循环机制案例分析
本文通过实例详细分析了JS中事件循环机制的原理和用法。以下是全部内容:
var start=new date()settimeout(function(){ var end=new date console . log(' time approach : ',end-start,' ms')},500)while(new date()-start 1000){ }还有其他语言可以完成预期的功能吗?Java,在Java.util.Timer中,定时任务的解决方案是通过多线程实现的,任务对象存储在任务队列中,特殊的调度线程在新的子线程中完成任务的执行
Js是单线程的
JavaScript的主要目的是与用户交互和操纵DOM。这就决定了它只能是单线程,否则会带来复杂的同步问题。
为了利用多核CPU的计算能力,HTML5提出了Web Worker标准,允许JavaScript脚本创建多个线程,但子线程完全由主线程控制,无法操作DOM。因此,这个新标准并没有改变JavaScript单线程的本质。
函数调用堆栈和任务队列
调用栈
JS执行时,会形成一个调用栈。当一个函数被调用时,返回地址、参数和局部变量都将被推入堆栈。如果在当前运行的函数中调用另一个函数,该函数的相关内容也将被推到堆栈的顶部。函数执行时,会弹出调用栈。变量会随之弹出。因为复杂的类型值存储在堆中,所以只弹出指针,它们的值仍然在堆中,这是由GC决定的。
事件循环任务队列(任务队列)
JavaScript主线程有一个执行堆栈和一个任务队列
在异步操作的情况下(如setTimeout、AJAX),异步操作将由浏览器(OS)执行。这些任务完成后,浏览器会将预定义的回调函数推入主线程的任务队列。当主线程的执行栈被清空时,它将读取任务队列中的回调函数。当任务队列被读取时,主线程将执行,从而进入一个无限循环,称为事件循环。
主线程执行栈的任务队列循环执行,形成事件循环
结论
SetTimeout()只是将事件插入到‘任务队列’中,主线程在执行当前代码(执行栈)之前不会执行它指定的回调函数。如果当前代码需要很长时间,可能需要等待很长时间,因此不能保证回调函数会在setTimeout()指定的时间执行。
另一个例子
(function test(){ setTimeout(function(){ console . log(4)),0);new Promise(函数执行器(解析){ console . log(1);for(var I=0;i10000I){ I==9999 resolve();} console . log(2);}).然后(function(){ console . log(5);});console . log(3);})()宏任务微任务
宏任务和微任务是异步任务的两种类型。暂停任务时,JS引擎会将所有任务按照类别划分到这两个队列中。首先取出macrotask队列中的第一个任务(这个队列也叫任务队列),然后取出microtask Queue中的所有任务依次执行;之后,进行宏任务,并重复该循环,直到两个队列中的任务都被取出。
宏任务:脚本(全代码),settimeout,setinterval,setimmediate,I/o,ui渲染微任务:process。nexttick,promises(这里指的是浏览器实现的原生promise),object。观察者,突变观察者
结论
编写宏任务脚本-微任务队列(带承诺。然后)-宏任务(settimeout)-下一个微任务
Node.js的事件循环
process.nextTick setImmediate
process.nextTick指定的任务总是发生在所有异步任务之前
由设置立即指定的任务总是在下一个事件循环中执行
process.nextTick(函数A(){ console . log(1);process.nextTick(函数B(){ console . log(2);});});setTimeout(函数超时(){ console . log(' time out FILEED '));},0)新的Promise(函数(resolve){ console . log(' glob 1 _ Promise ');resolve();}).then(function(){ console . log(' glob 1 _ then ')})process . nextTick(function(){ console . log(' glob 1 _ nextTick ');})
版权声明:js事件循环机制案例分析是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。