最近又碰到了event loop问题,之前研究的实在是浅显(https://www.cnblogs.com/zx0423/p/12641637.html)所以今天主要讲述promise的链式调用,async/await,requestAnimationFrame以及MutationObserver()。

1、Promise链式调用

    new Promise((resolve,reject)=>{
console.log("promise1");
resolve();
}).then(()=>{
//callback1
console.log("then11");
new Promise((resolve,reject)=>{
console.log("promise2");
resolve();
}).then(()=>{
// callback2
console.log("then21");
}).then(()=>{
// callback4
console.log("then23");
})
}).then(()=>{
// callback3
console.log("then12");
})

/*
1、new promsie是同步代码,立即执行
2、外部promise第一个then需要等外部promise被resolve后才执行,外部promise立即被resolve,于是执行注册的 then回调。此时外部第二then并未执行,因为他等待的是外部第一个then返回的promise
3、进入外部第一个then,回调里面是一个promise,执行内部promise时,同样两个then链式调用,内部第一个then执 行后,内部promise算执行完,返回一个新的promise给内部第二then用
4、外部第一个then执行完且有返回值,进入外部第二then
5、之后执行内部第二then
*/

解释:

// 行2 ,执行同步的executor函数
栈【 promise 】
宏任务队列【】
微任务队列【 callback1 】
执行结果:promise1
// 行7
栈【 callback1 】
宏任务队列【】
微任务队列【 callback2,callback3 】
执行结果:promise1 , then11 , promise2
//
栈【 callback2,callback3 】
宏任务队列【】
微任务队列【 callback4 】
执行结果:promise1 , then11 , promise2 , then21 , then12 ,
// 行16
栈【 callback4 】
宏任务队列【】
微任务队列【 】
执行结果:promise1 , then11 , promise2 , then21 , then12 , then23

️ 当行8添加 return 语句的时候,答案就截然不同了,大家可以自行体会一下。

2、async/await

  • async函数

  • 返回一个 Promise 对象

     async function test() {
    return 1; // async的函数 在这里隐式 使用 Promise.resolve(1)
    }

    //===>等价于
    new Promise(function(resolve, reject) {
    resolve(1);
    })
  • await

    每次我们使用 await, 解释器都创建一个 promise 对象,然后把剩下的 async 函数中的操作放到 then 回调函数中。async/await 的实现,离不开 Promise。

    1-await后面不是Promise对象,即是一些直接量 / 数值之类的
    • await会阻塞后面的代码,

      • 从右到左执行,

      • 再执行async外面的同步代码,

      • 同步代码执行完,再回到async内部,

      • 把这个非promise的东西,作为 await表达式的结果。

    2-await后面是Promise对象
    • await 它会“阻塞”后面的代码,

      • 从右到左执行,

      • 再执行async外面的同步代码,

      • 【期间不管宏任务微任务,就一直执行,直到...】

      • 直到 Promise 对象 resolved(也就是要等到了结果),即把 resolve 的 参数/值 作为 await 表达式的运算结果。

    理清上述执行顺序,对下面这道题就可以迎刃而解了。

 // async/await 与 then链式调用
async function f1(){
console.log("1");
await 'await的结果'
console.log("3")
} f1(); new Promise(function(resolve){
console.log("2")
resolve();
}).then(function(result){
new Promise( r => r()).then(() =>{
console.log(4)
}).then(()=>{
console.log(5);
})
}) 结果: 1,2,3,4,5

3、requestAnimationFrame & MutationObserver()

基本概念: Window.requestAnimationFrame(callback):告诉浏览器——希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画;
      MutationObserver():会在指定的DOM发生变化时被调用。【微任务,很好理解,按照正常的执行顺序执行即可】

大家先来看一段代码吧,思考一下他的执行结果是什么?然后在刷新看看,结果还是不是一样的了?

<div id="testElement"></div>
 setTimeout(() => {
console.log(performance.now(), 'settimeout');
}, 0) requestAnimationFrame(() => {
   console.log(performance.now(),'requestAnimationFrame');
}) const testElement = document.getElementById('testElement'); var observer = new MutationObserver(() => {
console.log('MutationObserver');
}); observer.observe(testElement, {
childList: true
})
//添加子节点,触发MutationObserver()
const div = document.createElement('div');
testElement.appendChild(div); new Promise(resolve => {
console.log('promise');
resolve();
}).then(() => console.log('then')) console.log(performance.now(), 'global');

如图:

可以看到,requestAnimationFrame的执行顺序是不一致的,

  起初,我将requestAnimationFrame归到宏任务中,原因是它绝大多数都会在setTimeout回调执行之后才执行。并将这个结果解释为是由于浏览器在执行渲染的时候,每次执行的时间会有差异,所以导致requestAnimationFrame和setTimeout被压入调用栈的时机不一致,也就导致了回调的时间不一致。

但是,可以看到宏任务与raf任务有明显的差异:
  执行时机不同;
  raf任务队列被执行时,会将其此刻队列中所有任务都执行完,既不属于宏任务/微任务,同时还排在微任务之后。

而且,在一个loop中,可能并不会执行这一步,只要浏览器任务不需要执行渲染,就会跳过。所以会出现requestAnimationFrame顺序不一致的状况。

EventLoop-浏览器篇2的更多相关文章

  1. 前端面试总结——http、html和浏览器篇

    1.http和https https的SSL加密是在传输层实现的. (1)http和https的基本概念 http: 超文本传输协议,是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和 ...

  2. 浏览器事件循环 & nodejs事件循环

    第1篇:如何理解EventLoop——宏任务和微任务篇 宏任务(MacroTask)引入 在 JS 中,大部分的任务都是在主线程上执行,常见的任务有: 渲染事件 用户交互事件 js脚本执行 网络请求. ...

  3. 如何理解EventLoop--浏览器篇

    前言 最近在准备春招,刷到了JS中的主要运行机制--Event Loop,觉得它的实现思路有必要整理一下,以防忘记.关于它在浏览器上的实现,我结合了自己的理解以及示例代码,想用最通俗的语言表达出来.如 ...

  4. 浏览器如何执行JS

    作为JS系列的第一篇,内容当然是浏览器如何执行一段JS啦. 首先通过浏览器篇我们可以得知,JS是在渲染进程里的JS引擎线程执行的.在此之后还要了解几个概念,编译器(Compiler).解释器(Inte ...

  5. Event Loop

    Event Loop 是 JavaScript 异步编程的核心思想,也是前端进阶必须跨越的一关.同时,它又是面试的必考点,特别是在 Promise 出现之后,各种各样的面试题层出不穷,花样百出.这篇文 ...

  6. 总结:JavaScript异步、事件循环与消息队列、微任务与宏任务

    本人正在努力学习前端,内容仅供参考.由于各种原因(不喜欢博客园的UI),大家可以移步我的github阅读体验更佳:传送门,喜欢就点个star咯,或者我的博客:https://blog.tangzhen ...

  7. (转)总结:JavaScript异步、事件循环与消息队列、微任务与宏任务

    前言 Philip Roberts 在演讲 great talk at JSConf on the event loop 中说:要是用一句话来形容 JavaScript,我可能会这样: “JavaSc ...

  8. html5手机常见问题与工具分享

    mobileTech A useful tools or tips list for mobile web application developing 这个项目收集移动端开发所需要的一些资源与小技巧 ...

  9. mobileTech

    A useful tools or tips list for mobile web application developing 这个项目收集移动端开发所需要的一些资源与小技巧 工具类网站 HTML ...

  10. TGL站长关于常见问题的回复

    问题地址: http://www.thegrouplet.com/thread-112923-1-1.html 问题: 网站配有太多的模板是否影响网站加载速度 月光答复: wp不需要删除其他的模板,不 ...

随机推荐

  1. PHP array_combine() 函数

    ------------恢复内容开始------------ 实例 通过合并两个数组来创建一个新数组,其中的一个数组元素为键名,另一个数组元素为键值: <?php$fname=array(&qu ...

  2. PHP idate() 函数

    ------------恢复内容开始------------ 实例 格式化本地时间/日期为整数.测试所有不同的格式: <?phpecho idate("B") . " ...

  3. PHP preg_replace() 函数

    preg_replace 函数执行一个正则表达式的搜索和替换.高佣联盟 www.cgewang.com 语法 mixed preg_replace ( mixed $pattern , mixed $ ...

  4. Skill 脚本演示 ycAlignAll.il

    https://www.cnblogs.com/yeungchie/ ycAlignAll.il 将版图整体对齐至 指定象限 / 原点,可以忽略 Label 干扰带来的 offGrid 的风险. 回到 ...

  5. 《分享》Koa2源码分析

    曾经在公司内部做的一起关于koa源码的分享,希望对你有帮助: koa2 源码分析整理 koa2(2.4.1版本)源码主要包含四个js,包括application.js, context.js, req ...

  6. Mac IDEA 免激活破解版 亲测有效 2020.8.1记

    开局一张图 下载地址 链接: https://pan.baidu.com/s/1OKbYCRQiZ3ip0Gzle5wydg 密码: iwfb 步骤 卸载之前的IDEA(没安装过,可忽略) 将下载后的 ...

  7. JSP中contentType、pageEncoding和meta charset的区别

    1.创建JSP 使用Eclipse创建JSP文件: <%@ page language="java" contentType="text/html; charset ...

  8. java web 下载文件 response.setHeader()的用法 (转载)

    response.setHeader()的用法 response.setHeader()下载中文文件名乱码问题 收藏 1. HTTP消息头 (1)通用信息头 即能用于请求消息中,也能用于响应信息中,但 ...

  9. QT QMdiArea 添加背景或添加背景图片失效问题

    说起QMdirArea 这个控件与其他控件真所不同.... 这里记一下 我踩过的坑之一,,,,, QMdiArea 默认的背景 不符合我要求,,当时我就理所当然就想往常一样给它设置颜色 万万没想到.. ...

  10. golang 字符型

    目录 前言 1. 基本 介绍 2. 声明 3. 使用细节 4. 字符类型的本质 跳转 前言 不做文字的搬运工,多做灵感性记录 这是平时学习总结的地方,用做知识库 平时看到其他文章的相关知识,也会增加到 ...