精华内容
参与话题
问答
  • 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();
    	//绿 红 黄
    
    展开全文
  • JavaScript系列—宏任务和微任务

    千次阅读 2019-07-07 22:25:28
    看这篇博文之前,先看一下下面的文章吧 《JavaScript 运行机制详解:再谈Event Loop》 ... 本文有参考,微信搜索《重学前端 --- Promise里的代码为什么比...关于宏任务和微任务 先看几道题吧 var r = new Pro...

    看这篇博文之前,先看一下下面的文章吧

    《JavaScript 运行机制详解:再谈Event Loop》

    http://www.ruanyifeng.com/blog/2014/10/event-loop.html

    本文有参考,微信搜索《重学前端 --- Promise里的代码为什么比setTimeout先执行?》

    关于宏任务和微任务

    先看几道题吧

       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

    再回头来看看开头的一段代码,会不会豁然开朗了呢。JS 引擎首先会把Promise对象 和 console.log("b") 两个微观任务存入执行栈,把 setTimeout(宏观任务)存入 “任务队列”

    所以在输出 a 和 b 以后并不会按照预期那样立即从 “任务队列” 中读取 setTimeout,因为 then方法是微观任务Promise对象的回调函数,先于 setTimeout 执行

      Promise.resolve().then(()=>{
        console.log('1')
        setTimeout(()=>{
          console.log('2')
        },0)
      })
    
      setTimeout(()=>{
        console.log('3')
        Promise.resolve().then(()=>{
          console.log('4')
        })
      },0)

    打印1 3 4 2

    在交流群中看到有的小伙伴还是不太清楚正确的执行顺序,基于前面的介绍,大致的分析过程及草图如下:

     

    1(红色):JS 引擎会把微观任务Promise存入执行栈,把宏观任务setTimeout存入 “任务队列”

    2(绿色):主线程率先运行执行栈中的代码,依次输入1,然后把绿框的setTimeout存入 “任务队列”

    3(蓝色):执行栈清空以后,会率先读取 “任务队列” 中最早存入的setTimeout(红框的那个),并把这个定时器存入栈中,开始执行。这个定时器中的代码都是微观任务,所以可以一次性执行,依次输出3 和 4

    4(紫色):重复第3步的操作,读取 “任务队列” 中最后存入的setTimeout(绿框的那个),输出2

    所以最终的输出结果就是 1 3 4 2

     

     

      Promise.resolve().then(()=>{
        console.log('1')
        setTimeout(()=>{
          console.log('2')
        },0)
      })
    
      setTimeout(()=>{
        console.log('3')
        Promise.resolve().then(()=>{
          console.log('4')
        })
      }, 3000)
    

    打印1 2 3 4

      setTimeout(function(){console.log(4)},0); 
      
      new Promise(function(resolve){ 
        console.log(1) 
        for( var i=0 ; i<10000 ; i++ ){
           i==9999 && resolve() 
        } 
        console.log(2) 
      }).then(function(){ 
        console.log(5) 
      }); 
      console.log(3);

    另外一个会让人感到迷惑的地方就是 resolve回调函数内部的那几行代码,输出1以后接着跑1000次循环才调用resolve方法,其实resolve()的意思是把 Promise对象实例的状态从pending变成 fulfilled(即成功)

    成功的回调就是对应的then方法。所以resolve() 后面的 console.log(2) 会先执行,因为 resolve() 回调函数是在本轮事件循环的末尾执行 (关于这部分内容,可以参考  Promise对象 一文)

    打印1 2 3 5 4

      setTimeout(function(){console.log(4)},0); 
      
      new Promise(function(resolve){ 
        console.log(1) 
        for( var i=0 ; i<10000 ; i++ ){
          //  i==9999 && resolve() 
        } 
        console.log(2) 
      }).then(function(){ 
        console.log(5) 
      }); 
      console.log(3);

    打印1 2 3 4

    展开全文
  • 先以一道面试题做引子: 写出这段程序的输出内容: setTimeout(function(){ console.log(1); },0); new Promise(function(a,b){ console.log(2); for(var i=0;i&lt;10;i++)...

    先以一道面试题做引子:

    写出这段程序的输出内容:

            setTimeout(function(){
                console.log(1);
            },0);
            new Promise(function(a,b){
                console.log(2);
                for(var i=0;i<10;i++){
                    i==9&&a();
                }
                console.log(3)
            }).then(function(){
                console.log(4)
            });
            console.log(5);

    正确输出顺序为:2,3,5,4,1;

    如果你看了这道题不知道怎么下手,或者发现结果和自己的答案大相径庭,请继续往下看

    1. javascript事件循环

    首先,你要知道javascript是单线程语言。js任务需要排队顺序执行,如果一个任务耗时过长,后边一个任务也的等着,但是,假如我们需要浏览新闻,但新闻包含的超清图片加载很慢,总不能网页一直卡着直到图片完全出来,所以将任务设计成了两类:

    • 同步任务
    • 异步任务

    当我们打开网站时,网页的渲染过程就是一大堆同步任务,像页面骨架和页面元素的渲染,而加载图片、音乐之类的任务就是异步任务,看一下下边导图:

    如图:

    同步和异步任务分别进入不同的执行“场所”,同步进入主线程,异步进入Event Table并注册函数。当指定的事情完成时,Event Table会将这个函数移入Event Queue。主线程内的任务执行完毕为空,回去了Event Queue读取对应的函数,进入主线程。

    上述过程会不断重复,也就是常说的Event Loop(事件循环)。

    但是,JS异步还有一个机制,就是遇到宏任务,先执行宏任务,将宏任务放入event queue,然后再执行微任务,将微任务放入eventqueue,但是,这两个queue不是一个queue。当你往外拿的时候先从微任务里拿这个回调函数,然后再从宏任务的queue拿宏任务的回调函数,如下图:

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

    微任务:Promise,process.nextTick

     

    借鉴自网友文章 Javascript执行机制

     

     

     

    展开全文
  • 为了协调事件、用户交互、脚本、UI 渲染网络处理等行为,防止主线程的不阻塞,Event Loop 的方案应用而生。Event Loop 包含两类:一类是基于 Browsing Context,一种是基于 Worker。二者的运行是独立的,也就是说...
  • js 异步的 宏任务和微任务

    千次阅读 2018-05-29 21:48:43
    &lt;!DOCTYPE html&gt;&lt;html lang="en"&gt;&lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;meta name="viewport" content="...
  • javascript的宏任务和微任务 宏任务有Event Table、Event Queue,微任务有Event Queue 1.宏任务:包括整体代码script,setTimeout,setInterval; 2.微任务:Promise,process.nextTick 注:Promise立即执行,...
  • 关于宏任务微任务和事件循环

    千次阅读 2020-04-06 00:12:27
    我想很多人都见过或听过这种题。 setTimeout(() => { console.log('settimeout') }); new Promise((resolve) => { resolve(''); console.log('promise-resolve'); }).then(() =>......
  • 1. setTimeout(function() { console.log('1') }); new Promise(function(resolve) { console.log('2'); resolve(); }).then(function() { console.log('3') }); ...
  • 从vue.nextTick看宏任务和微任务

    千次阅读 2018-10-01 14:24:12
    Vue 是异步执行 DOM 更新的,其中nextTick就是等待操作完成再执行dom操作,vue.nextTick是vue实现生命周期的重要API函数,官方文档对...vue.nextTick的实现就是根据宏任务微任务,我们可以中github中查看nextT...
  • 异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行。这里说到了一个“队列”(即任务队列),该...
  • 不论你是javascript新手还是老鸟,不论是面试求职,还是日常开发工作,我们经常会遇到这样的情况:给定的几行代码,我们需要知道其输出内容顺序。因为javascript是一门单线程语言,所以我们...
  • 宏任务和微任务的一道经典面试题~

    千次阅读 2020-03-28 16:20:15
    async function async1 () { console.log('async1 start'); await async2(); console.log('async1 end') } async function async2 () { console.log('async2') } console.log('script start'...
  • js 微任务 宏任务的执行顺序解释

    千次阅读 2019-07-26 09:23:51
    js 微任务 宏任务的执行顺序解释 js 是单线程执行的,js中的任务按顺序一个一个的执行,但是一个任务耗时太长,那么后面的任务就需要等待,为了解决这种情况,将任务分为了同步任务和异步任务,而异步任务又可以...
  • 写出下列代码打印的顺序: setTimeout(() => { console.log(4); }, 0); new Promise(resolve=>{ console.log(1); for(let i =0;i<10000;i++){ ...
  • 先看一到面试题 写出console.log的输出顺序 console.log(100); setTimeout(()=>{ console.log(200); }) setTimeout(()=>{ console.log(201); }) Promise.resolve().then(()=>...// 为什么300比200
  • js宏任务微任务

    千次阅读 2019-04-24 17:14:54
    当我们打开网站时,网页的渲染过程就是一大堆同步任务,比如页面骨架页面元素的渲染。而像加载图片音乐之类占用资源大耗时久的任务,就是异步任务。关于这部分有严格的文字定义,但本文的目的是用最小的学习成本...
  • 甚或是执行多分类任务,每两两类别的组合都对应一个混淆矩阵。总之,我们希望在n个二分类混淆矩阵上综合考察查准率查全率。 二分类的分类结果混淆矩阵 真实情况/预测结果 正例 反例 正例 TP(真正例) FN...
  • 2. 宏任务和微任务 概念 宏任务 微任务 例题 EXP1: 在主线程上添加宏任务与微任务 EXP2: 在微任务中创建微任务 EXP3: 宏任务中创建微任务 EXP4:微任务队列中创建的宏任务 总结 这篇博文仅为个人理解,文章...

空空如也

1 2 3 4 5 ... 20
收藏数 648,267
精华内容 259,306
关键字:

任务