• javaScript 事件循环机制


    JavaScript是单线程的编程语言,只能同一时间内做一件事。但是在遇到异步事件的时候,js线程并没有阻塞,还会继续执行,这就是因为JS有事件循环机制。

    事件循环流程总结

    1. 主线程开始执行一段代码, 假设开始执行一个 script 标签内的代码,将代码放入执行栈中执行,同步代码优先执行,执行过程中,当遇到任务源时,判断是宏任务还是微任务。
    2. 如果是宏任务,加入到宏任务队列中,如果是微任务,加入到微任务队列中。
    3. 同步代码执行完成,执行栈空闲,检查微任务队列中是否有可执行任务,如果有,依次执行所有微任务队列中的任务。如果没有。当前任务执行结束。
    4. 渲染UI。
    5. 检查宏任务队列是否有可执行的宏任务,如果有,取出队列中最前面的那个宏任务,加入到执行栈中开始执行,然后重复前面步骤,直到宏任务队列中所有任务执行结束。

    async/await执行顺序

    我们知道async隐式返回 Promise 作为结果的函数,那么可以简单理解为,await后面的函数执行完毕时,await会产生一个微任务(Promise.then是微任务)。
     
    但是我们要注意这个微任务产生的时机,它是执行完await之后,直接跳出async函数,执行其他代码(此处就是协程的运作,A暂停执行,控制权交给B)。
     
    其他代码执行完毕后,再回到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')
    })
    
    async1()
    
    new Promise(function (resolve) {
        console.log('promise1')
        resolve()
    }).then(function () {
        console.log('promise2')
    })
    
    console.log('script end')
    
    // 'script start' => 'async1 start' => 'async2' => 'promise1' => 'script end' => 'async1 end' => 'promise2' => 'settimeout'
    const p = Promise.resolve();
    
    (async () => {
        await p;
        console.log('await end');
    })();
    
    p.then(() => {
        console.log('then 1');
    }).then(() => {
        console.log('then 2');
    });
    // 'then 1' => 'then 2' => 'await end'
    // 1. 开始执行
    
    console.log(1)     // 2. 打印 1
    
    
    setTimeout(function () {    // 6. 浏览器在 0ms 后,将该函数推入任务队列
        console.log(2)    // 7. 打印 2
        Promise.resolve(1).then(function () {    // 8. 将 resolve(1) 推入任务队列  9. 将 function函数推入任务队列
            console.log('ok')    // 10. 打印 ok
        })
    })    // 3.调用 setTimeout 函数,并定义其完成后执行的回调函数
    
    
    setTimeout(function () {        // 11. 浏览器 0ms 后,将该函数推入任务队列
        console.log(3)    // 12. 打印 3
    })    // 4. 调用 setTimeout 函数,并定义其完成后执行的回调函数
    
    // 5. 主线程执行栈清空,开始读取 任务队列 中的任务
    
    // output: 1  2 ok 3

     

  • 相关阅读:
    JPA-基本注解
    响应式、自适应式
    Spring boot传值注意事项
    Angular与Vue
    Java 时间转换
    SpringBoot 上传读取图片 巨坑
    前后端分离之 文件上传
    System.nanoTime与System.currentTimeMillis
    sqlserver 新增子段有默认值
    json转换
  • 原文地址:https://www.cnblogs.com/yuwenxiang/p/16579233.html
Copyright © 2020-2023  润新知