精华内容
参与话题
问答
  • 宏任务和微任务

    2018-11-11 22:03:18
    概念011. 宏任务:当前调用栈中执行的代码成为宏任务。(主代码快,定时器等等)。2.微任务: 当前(此次事件循环中)宏任务执行完,在下一个宏任务开始之前需要执行的任务,...
        

    概念

    01


    1. 宏任务:当前调用栈中执行的代码成为宏任务。(主代码快,定时器等等)。

    2.微任务: 当前(此次事件循环中)宏任务执行完,在下一个宏任务开始之前需要执行的任务,可以理解为回调事件。(promise.then,proness.nextTick等等)。

    3. 宏任务中的事件放在callback queue中,由事件触发线程维护;微任务的事件放在微任务队列中,由js引擎线程维护。


    运行机制

    02


    1. 在执行栈中执行一个宏任务。

    2. 执行过程中遇到微任务,将微任务添加到微任务队列中。

    3. 当前宏任务执行完毕,立即执行微任务队列中的任务。

    4. 当前微任务队列中的任务执行完毕,检查渲染,GUI线程接管渲染。

    5. 渲染完毕后,js线程接管,开启下一次事件循环,执行下一次宏任务(事件队列中取)。


    展开全文
  • javascript的宏任务和微任务

    万次阅读 多人点赞 2018-04-11 20:28:19
    今天进行了人生中的第一次面试。结果凉凉了。但是还是学到了很多东西。其中在面试时面试官问了我一道题 setTimeout(function(){ console.log('1') }); ... new Promise(function(resolve){ ...

    今天进行了人生中的第一次面试。结果凉凉了。但是还是学到了很多东西。其中在面试时面试官问了我一道题

    setTimeout(function(){
    		    console.log('1')
    		});
    
    		new Promise(function(resolve){
    		    console.log('2');
                        resolve();
    		}).then(function(){
    		    console.log('3')
    		});
    
    		console.log('4');

    请你给出这段代码的运行顺序。当时我就蒙犊子了。同步异步我看过很多的讲解,大多都是要么你就一个setTimeout函数,要么就一个Promise函数。两个函数放到一起的我还真没见过。于是我就想:

    settimeout肯定是异步的。 我也知道有一个event队列,你settimeout没设置时间应该直接就进入这个队列了吧,然后就是Promise的回掉函数进入event队列。 当时我二话不说给了个答案 2,4,1,3.并且很自信。然后面试官就问你不想想了?我说不想了。然后后半段他全程开始皱眉头了。我也凉凉。最后他让我回去看一下宏任务和微任务。

    首先说一下普通的异步函数的执行过程吧:

     

    同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。当指定的事情完成时,Event Table会将这个函数移入Event Queue。主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。上述过程会不断重复,也就是常说的Event Loop(事件循环)。

    图文我是转载的一个掘金的老哥的文章里的。他叫:ssssyoki

     

    ssssyoki

    那么如此看来我给的答案还是对的。但是js异步有一个机制,就是遇到宏任务,先执行宏任务,将宏任务放入eventqueue,然后在执行微任务,将微任务放入eventqueue最骚的是,这两个queue不是一个queue。当你往外拿的时候先从微任务里拿这个回掉函数,然后再从宏任务的queue上拿宏任务的回掉函数。 我当时看到这我就服了还有这种骚操作。

    再盗个图

    而宏任务一般是:包括整体代码script,setTimeout,setInterval。

    微任务:Promise,process.nextTick。

    记住就行了。

    然后回到开头的代码。因为settimeout是宏任务,虽然先执行的他,但是他被放到了宏任务的eventqueue里面,然后代码继续往下检查看有没有微任务,检测到Promise的then函数把他放入了微任务序列。等到主线进程的所有代码执行结束后。先从微任务queue里拿回掉函数,然后微任务queue空了后再从宏任务的queue拿函数。

    所以正确的执行结果当然是:2,4,3,1。

    如果还是不懂得同学可以去看一下这个老哥的文章,总结的挺到位的。向他学习。点击打开链接

    展开全文
  • JavaScript 宏任务和微任务

    千次阅读 2019-06-17 15:12:04
    JavaScript 宏观任务和微观任务 概念 宏观任务:宿主发起的任务为宏观任务,如setTimeout、setInterval、setImmediate,I/O 微观任务:JavaScript引擎发起的任务为微观任务,如Promise JavaScript引擎等待宿主环境...

    JavaScript 宏观任务和微观任务

    概念

    在这里插入图片描述
    宏观任务:宿主发起的任务为宏观任务,如setTimeout、setInterval、setImmediate,I/O
    微观任务:JavaScript引擎发起的任务为微观任务,如Promise

    JavaScript引擎等待宿主环境分配宏观任务,宏观任务的队列可以理解为一个事件循环:

    while(TRUE) {
      r = wait();
      execute(r);
    }
    

    每个宏观任务中又包含一个微观任务队列
    有:

    • setTimeout等宿主API,会添加宏观任务
    • Promise永远在队列尾部添加微观任务

    分析异步执行的方法

    1. 分析有多少个宏观任务
    2. 在每个宏观任务中,分析有多少个微观任务
    3. 根据调用次序,确定宏观任务中微观任务执行次序
    4. 根据宏观任务调用次序和触发原则,确定宏观任务执行次序
    5. 确定整个次序

    promise

     var r = new Promise(function(resolve, reject) {
          console.log("a");
          resolve();
        });
        setTimeout(() => console.log("d"), 0);
        r.then(() => console.log("c"));
        console.log("b");
    
        // 执行顺序 a b c d
    
    
    
        setTimeout(() => console.log("d"), 0);
        var r1 = new Promise(function(resolve, reject) {
          resolve();
        });
        r1.then(() => {
          var begin = Date.now();
          while (Date.now() - begin < 1000);
          console.log("c1");
          new Promise(function(resolve, reject) {
            resolve();
          }).then(() => console.log("c2"));
        });
        // 虽然第二个promise 间隔了1秒 但是还是 先于setTimeout执行
        // c1  c2  d
       
    
    function sleep(duration) {
          return new Promise(function(resolve, reject) {
            console.log("b");
            setTimeout(resolve, duration);
          });
        }
        console.log("a");
        sleep(5000).then(() => console.log("c"));
    
        // 将setTimeout封装成可以用于异步的函数
     	//a b c
    
    

    async/await

    是ES7新特性,提供了用for if来编写异步代码的方式
    async函数必定返回Promise,所有返回Promise的函数都可以认为是异步函数

    • async用来表示函数是异步的,定义的函数会返回一个promise对象,可以使用then方法添加回调函数。我们把所有返回 Promise 的函数都可以认为是异步函数。[所以它也是微观任务]

    • await 后面可以跟任何的JS 表达式。虽然说 await 可以等很多类型的东西,但是它最主要的意图是用来等待 Promise 对象的状态被 resolved。如果await的是 promise对象会造成异步函数停止执行并且等待 promise 的解决,如果等的是正常的表达式则立即执行。

    async可以嵌套

    function sleep(duration) {
      return new Promise(function(resolve, reject) {
        setTimeout(resolve, duration)
      })
    }
    async function foo(name) {
      await sleep(2000)
      console.log(name)
    }
    async function foo2() {
      await foo("a")
      await foo("b")
    }
    foo2()
    //a b
    
       var obj = document.getElementById("animate");
        function timeSleep(times) {
          return new Promise((resolve, reject) => {
            setTimeout(resolve, times);
          });
        }
       async function colorChange(color, times) {
          obj.style.backgroundColor = color;
          await timeSleep(times);
        }
    
        async function trafciLigth() {
          // while (true) {
          await colorChange("green", 3000);
          await colorChange("red", 2000);
          await colorChange("yellow", 1000);
          // }
        }
        trafciLigth();
    	//绿 红 黄
    
    展开全文
  • js 宏任务和微任务

    2019-05-22 15:49:44
    js 宏任务和微任务 宏任务(macrotask )和微任务(microtask )macrotask 和 microtask 表示异步任务的两种分类。 在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 macrotask 的队列(这个队列...

    js 宏任务和微任务

    宏任务(macrotask )和微任务(microtask )macrotask 和 microtask 表示异步任务的两种分类。
    在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 macrotask 的队列(这个队列也被叫做 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的所有任务顺序执行;之后再取 macrotask 任务,周而复始,直至两个队列的任务都取完。

    如下图所示:
    在这里插入图片描述
    宏任务和微任务之间的关系
    在这里插入图片描述
    注意一点:

    宏任务需要多次事件循环才能执行完,微任务是一次性执行完的;

    举个栗子:

    setTimeout(() => {
        //执行后 回调一个宏事件
        console.log('内层宏事件3')
    }, 0)
    console.log('外层宏事件1');
    
    new Promise((resolve) => {
        console.log('外层宏事件2');
        resolve()
    }).then(() => {
        console.log('微事件1');
    }).then(()=>{
        console.log('微事件2')
    })
    

    输出结果:

    外层宏事件1
    外层宏事件2
    微事件1
    微事件2
    内层宏事件3
    

    • 首先浏览器执行js进入第一个宏任务进入主线程, 遇到 setTimeout 分发到宏任务Event Queue中

    • 遇到 console.log() 直接执行 输出 外层宏事件1

    • 遇到 Promise, new Promise 直接执行 输出 外层宏事件2

    • 执行then 被分发到微任务Event Queue中

    •第一轮宏任务执行结束,开始执行微任务 打印 ‘微事件1’ ‘微事件2’

    •第一轮微任务执行完毕,执行第二轮宏事件,打印setTimeout里面内容’内层宏事件3’

    宏任务


    方法 浏览器 Node
    setTimeout
    setInterval
    setImmediate x
    requestAnimationFrame x

    宏任务macrotask:
    (事件队列中的每一个事件都是一个macrotask)
    优先级:主代码块 > setImmediate > MessageChannel > setTimeout / setInterval
    比如:setImmediate指定的回调函数,总是排在setTimeout前面

    微任务

    方法 浏览器 Node
    process.nextTick x
    MutationObserver x
    Promise.then catch finally

    优先级:process.nextTick > Promise > MutationObserver

    再来个栗子:

    //主线程直接执行
    console.log('1');
    //丢到宏事件队列中
    setTimeout(function() {
        console.log('2');
        process.nextTick(function() {
            console.log('3');
        })
        new Promise(function(resolve) {
            console.log('4');
            resolve();
        }).then(function() {
            console.log('5')
        })
    })
    //微事件1
    process.nextTick(function() {
        console.log('6');
    })
    //主线程直接执行
    new Promise(function(resolve) {
        console.log('7');
        resolve();
    }).then(function() {
        //微事件2
        console.log('8')
    })
    //丢到宏事件队列中
    setTimeout(function() {
        console.log('9');
        process.nextTick(function() {
            console.log('10');
        })
        new Promise(function(resolve) {
            console.log('11');
            resolve();
        }).then(function() {
            console.log('12')
        })
    })
    

    • 首先浏览器执行js进入第一个宏任务进入主线程, 直接打印console.log(‘1’)

    • 遇到 setTimeout 分发到宏任务Event Queue中

    • 遇到 process.nextTick 丢到微任务Event Queue中

    • 遇到 Promise, new Promise 直接执行 输出 console.log(‘7’);

    • 执行then 被分发到微任务Event Queue中

    •第一轮宏任务执行结束,开始执行微任务 打印 6,8

    •第一轮微任务执行完毕,执行第二轮宏事件,执行setTimeout

    •先执行主线程宏任务,在执行微任务,打印’2,4,3,5’

    •在执行第二个setTimeout,同理打印 ‘9,11,10,12’

    •整段代码,共进行了三次事件循环,完整的输出为1,7,6,8,2,4,3,5,9,11,10,12。

    以上是在浏览器环境下执行的数据,只作为宏任务和微任务的分析,我在node环境下测试打印出来的顺序为:1,7,6,8,2,4,9,11,3,10,5,12。node环境执行结果和浏览器执行结果不一致的原因是:浏览器的Event loop是在HTML5中定义的规范,而node中则由libuv库实现。libuv库流程大体分为6个阶段:timers,I/O callbacks,idle、prepare,poll,check,close callbacks,和浏览器的microtask,macrotask那一套有区别。

    展开全文
  • 最近问了大佬一个问题,监听和定时器两个性能的问题,大佬给我普及了宏任务和微任务的概念,于是网上找见了这样一段代码: console.log('script start'); setTimeout(function() { console.log('setTimeout'); }...

空空如也

1 2 3 4 5 ... 20
收藏数 720
精华内容 288
关键字:

宏任务和微任务