zoukankan      html  css  js  c++  java
  • js执行顺序

    本篇随笔主要通过两个案例来梳理promise执行顺序和promise、async/await执行顺序,介绍之前默认大家已经了解这两个api的使用方法并且了解js宏任务与微任务概念。文章末尾会附上相关资料,有兴趣的可以查看。

    一、promise

    console.log('script start');
    
    setTimeout(function() {
      console.log('setTimeout');
    }, 0);
    
    Promise.resolve().then(function() {
      console.log('promise1');
    }).then(function() {
      console.log('promise2');
    });
    
    console.log('script end');

     大概看几眼,直接上答案和分析:script start、script end、promise1、promise2、setTimeout;

    开始分析:

    1、第一个输出大家都没问题,代码执行到第二行遇到setTimeout,js引擎把定时器回调函数当做一个宏任务放入回调队列(callback queue),让出js主线程继续往下执行;

    2、到第五行是个promise.resolve()异步执行函数(微任务),所以js引擎把then后面的回调函数放入当前调用栈末尾,让出js主线程继续往下执行。

    3、执行完最后一行,输出script end;此时at the end of a task,we process microtasks(当前宏任务执行完毕,开始执行微任务,也就是第2步中的),输出promise1,接着继续往下执行,又遇到了promise回调函数,所以也把第二个then后面的回调函数当成微任务放入当前调用栈末尾。

    4、因为当前调用栈中的微任务必须先于下一个宏任务执行,所以继续执行第3步中的微任务,输出promise2。

    5、当前调用栈中代码全部执行完,根据事件循环机制,js引擎将回调队列中宏任务放入调用栈中执行,输出setTimeout。

    二、promise、async/await

    async function async1(){
        console.log('async1 start')
        await async2()
        console.log('async1 end')
    }
    async function async2(){
        console.log('async2')
    }
    console.log('script start')
    setTimeout(function(){
        console.log('setTimeout') 
    },0)  
    async1();
    new Promise(function(resolve){
        console.log('promise1')
        resolve();
    }).then(function(){
        console.log('promise2')
    })
    console.log('script end')

    最后输出:

    script start

    async start

    async2

    promise1

    script end

    promise2

    async1 end

    setTimeout

    分析:

    1、首先输出script start,然后将setTimeout的回调函数当成一个宏任务放入回调队列,让出js主线程,执行async1()。虽然async1是用async声明的异步函数,但是他本身依旧是一个立即执行函数,所以进入async1,执行输出async start。

    2、直到遇到了await(async wait的缩写)这个熊孩子,看js是怎么处理他的。遇到await之后,js会执行完他后面的表达式/函数,然后跳出这个异步函数。这里呢,await后面跟的用async声明的async2异步函数,所以执行完,await后面是一个promise对象(未resolve),跳出async1。

    3、执行到new promise,立即输出promise1,然后是他的resolve(),所以暂停执行,把promise的回调函数当成一个微任务放到当前调用栈末尾,跳出promise,执行最后一行,输出script end。

    4、注意注意,下面的不好理解。接着执行第2步中的async1,此时await后面的promise开始resolve,所以js将async2函数的返回值(promise对象)的回调函数当做一个微任务,放到当前调用栈末尾,js主线程又让出async1函数。

    5、此时当前调用栈中宏任务执行完毕,立即按顺序执行微任务。也就是第3步中的,直接输出promise2。接着执行第4步中产生的微任务(当然,没有执行任何东西),这会之后,js才正式通过await那一行,输出async1 end。这就是为什么promie2先于async1 end 输出。

    6、扫扫尾,js执行下一个宏任务,输出setTimeout,到此全部结束。

    上面的我加粗的那两个输出内容,是大家最疑惑的地方,也是最不好理解的地方,希望大家可以好好解读一下我的分析。

    手敲不易,如果对你来说有一点帮助,请献出你们的免费推荐。下面是一些我参考的资料和一个学习资料。

    async/await编码的技巧

     promise、async和await之执行顺序的那点事

    Tasks, microtasks, queues and schedules

    Tasks, microtasks, queues and schedules(翻译)

    理解js中的async/await 

    学习资料

    掘进翻译计划

  • 相关阅读:
    异常详细信息: System.InvalidCastException: 对象不能从 DBNull 转换为其他类型——的解决方法
    .net显示今天农历的代码!
    在GridView中设置日期格式
    安装VS 2008 SP1后,智能提示变为英文的补丁发布
    SQL server无法执行查询,因为一些文件丢失或未注册等问题的解决
    SQL Server 2000企业管理器中MMC无法创建管理单元的解决方法
    FILTER:progid:DXImageTransform.Microsoft.Gradient使用
    [jQuery] event.stopPropagation()报错
    得到系统当前的dpi设置值
    VS2008 当前不会命中断点,还没有为该文档加载任何符号
  • 原文地址:https://www.cnblogs.com/js123/p/10775170.html
Copyright © 2011-2022 走看看