zoukankan      html  css  js  c++  java
  • JavaScript的执行机制

    JavaScript是单线程的,任务的执行时自上而下的,这就有了一个问题,当遇到一个比较耗时的任务时,下面的代码就会被阻塞,这就意味着卡死。所以js是有异步的,它的实现主要是通过事件循环(event loop)

    事件循环

    JavaScript中的任务分为两种:同步和异步

    按照分类,当有任务执行时:

    •   判断是同步还是异步,同步进入主线程,异步进入event table
    •   异步任务在event table中注册函数,当满足触发条件,推入event queue
    •   同步任务进入主线程后一直执行,直到主线程空闲时,才会到event queue中查看是否有可执行的异步任务,如果有就推入到主线程中执行

    以上三步循环执行,就是event loop

    看这幅图

     

    如:

            console.log("1")
    	setTimeout(function() {
    		console.log(2)
    	}, 1000)
    	console.log(3)    
    
    • consloe.log(1),同步任务,进入主线程
    • setTimeout(),异步任务,进入event table,1秒后进入event queue里
    • console.log(3),同步任务,放入主线程
    • 先执行主线程中的任务,此时,主线程有,打印1,打印3
    • 当主线程执行结束,主线程空闲,于是,主线程到event queue(事件队列)里查看是否有可执行的函数,于是打印2

     宏任务和微任务

    除了之前说过的同步任务和异步任务,还有更精细的定义:

    • macro-task(宏任务):包含整体代码script,setTimeout,setlnterval
    • micro-task(微任务):Promise,process.nextTick

    不同的任务会进入不同的event queue,比如setTimeout,setlnterval会进入相同的event queue,Promise,process.nextTick会进入相同的event queue

    事件循环的顺序,决定js代码的执行顺序,进入整体代码(宏任务)后,开始第一次循环。接着执行所有微任务。然后再从宏任务开始,待一个任务队列执行完毕,再执行微任务。代码演示

            console.log("start")
    	setTimeout(function(){
    		console.log("setTimeout")
    	},0)
    	
    	new Promise(function(resolve){
              resolve() console.log("promise") }).then(function(){ console.log("then") }) console.log("end")

      先按照最开始的方式解释,及同步任务和异步任务

    • console.log("start"),同步任务,进入主线程,直接打印
    • setTimeout,异步任务,进入event table
    • Promise,同步任务,进入主线程,直接打印
    • then,异步,放入event table
    • console.log("end")同步任务,直接打印
    • 结束,先执行主线程的任务,start => promise => end ,主线程结束,查看任务队列中是否有待执行的任务,打印 setTimeout => then
    • 即,start => promisr => end =>  setTimeout => then

    然而执行的结果却是这样的:start => promisr => end =>  then => setTimeout 

    所以我们要同过宏任务和微任务的方式解释

    • 首先执行script下的宏任务,遇到console.log("start"),直接打印 “start”
    • 遇到setTimeout,将其放入宏任务队列
    • 遇到promise,直接执行,打印 “promise”
    • 遇到then,微任务,放入微任务队列
    • 遇到console.log("end"),直接打印 “end”
    • 此时,整体script作为第一个宏任务执行结束,看看有没有微任务,发现有个then在微任务的event queue中,执行,打印“then”
    • 到此第一轮事件循环结束,开始第二轮事件循环,当然要从宏任务event queue开始,此时宏任务event queue中有setTimeout,立即执行,打印“setTimeout”
    • 结束,此时的顺序start => promisr => end =>  then => setTimeout 

    来看关系图

    最后

      要知道js是一门单线程语言,所有实现异步的方式,其实都是用同步模拟出来的,而事件循环event loop 是实现异步的一种方法,也是js的执行机制

  • 相关阅读:
    java项目中常用的定时任务实现方法
    mysql8.0只能本地连接解决方法
    自定义Mybatis Plus代码生成器(增加Vo类的生成)
    VMware的安装
    HDU 1728 逃离迷宫
    HDU2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
    HDU1059 Dividing
    HDU1114 Piggy-Bank
    HDU4508 湫湫系列故事——减肥记I
    HDU 2602 Bone Collector
  • 原文地址:https://www.cnblogs.com/aizz/p/9774092.html
Copyright © 2011-2022 走看看