浏览器渲染过程中如何处理异步任务

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
私网连接 PrivateLink,5万GB流量 1.5万小时实例时长
全球加速 GA,每月750个小时 15CU
简介: 在浏览器渲染过程中,异步任务通过事件循环机制处理。JS执行时,同步任务在主线程上执行,形成一个执行栈。异步任务则被推入任务队列中,待主线程空闲时按顺序调用,确保页面流畅渲染与响应。
  1. 浏览器渲染基础与异步任务的引入

    • 浏览器渲染流程概述:浏览器渲染主要包括解析HTML构建DOM树、解析CSS构建CSSOM(CSS对象模型)、将DOM树和CSSOM合并生成渲染树、布局(计算元素位置和大小)和绘制(将元素渲染到屏幕)等阶段。在这个过程中,JavaScript代码的执行会对渲染产生影响。
    • 异步任务的必要性:当JavaScript执行一些耗时的操作,如网络请求(fetch或XMLHttpRequest)、定时器(setTimeout、setInterval)等,如果这些操作是同步执行的,会阻塞浏览器的渲染,导致页面出现长时间的空白或无响应。因此,异步任务被引入,使得浏览器在执行这些耗时操作时可以继续进行其他渲染工作。
  2. 不同类型异步任务在渲染过程中的处理方式

    • 定时器(setTimeout/setInterval)
      • 任务排队机制:当执行setTimeoutsetInterval函数时,浏览器会将其回调函数注册为一个宏任务,并在指定的延迟时间后将该宏任务添加到宏任务队列中。例如,在页面加载时执行以下代码:
        console.log('Script start');
        setTimeout(() => {
                 
        console.log('Timeout callback');
        }, 1000);
        console.log('Script end');
        
      • 浏览器首先会执行同步代码,打印Script start,然后遇到setTimeout,将其回调函数注册为宏任务并等待1秒。接着继续执行同步代码打印Script end。1秒后,如果此时浏览器的调用栈为空且微任务队列也为空,就会执行setTimeout的回调函数,打印Timeout callback
      • 对渲染的影响:在定时器等待期间,浏览器可以正常进行渲染工作。但如果定时器回调函数中有修改DOM结构或样式的操作,会触发重新布局和重新绘制。例如,如果定时器回调函数中改变了一个元素的大小,浏览器会在执行该回调函数时重新计算布局并重新绘制页面。
    • 网络请求(Ajax、fetch)
      • 异步请求与回调处理:当使用fetchXMLHttpRequest进行网络请求时,这些请求会在后台异步进行。浏览器会发送请求,然后继续执行其他代码。当请求完成并收到响应后,对应的回调函数(对于fetch,是.then方法中的函数;对于XMLHttpRequest,是onreadystatechangeonload等事件处理函数)会被添加到宏任务队列中。例如:
        console.log('Request start');
        fetch('https://example.com/api/data')
        .then(response => response.json())
        .then(data => {
                 
         console.log('Data received:', data);
         // 在这里可能会更新DOM,触发渲染
        });
        console.log('Request sent');
        
      • 浏览器首先打印Request start,然后发送请求并继续打印Request sent。当数据返回后,处理数据的回调函数会被添加到宏任务队列,等待执行。如果在回调函数中有更新DOM的操作,如将获取的数据渲染到页面上的列表中,会触发DOM更新,导致浏览器重新渲染部分或全部页面。
      • 优化渲染性能:为了避免在数据返回后一次性更新大量DOM元素导致的性能问题,可以采用虚拟列表技术或者分批次更新DOM。例如,对于一个长列表数据的渲染,可以只渲染用户当前可视区域内的列表项,当用户滚动时再动态加载和渲染其他项。
    • Promise与微任务(Promise.then、MutationObserver)
      • 微任务的执行顺序:Promise的.then方法中的回调函数会被添加到微任务队列中。在当前宏任务(如包含Promise的脚本块)执行完毕后,浏览器会先清空微任务队列,再处理下一个宏任务。例如:
        console.log('Script start');
        const promise = Promise.resolve('Data');
        promise.then(result => {
                 
        console.log('Promise resolved:', result);
        });
        console.log('Script end');
        
      • 浏览器先打印Script start,然后将Promise.then回调函数添加到微任务队列。接着打印Script end,在当前宏任务结束后,浏览器会清空微任务队列,执行Promise.then回调函数,打印Promise resolved: Data
      • 与渲染的协同作用:微任务可以用于在合适的时机更新DOM,使得DOM更新与浏览器的渲染过程更加紧密地协同。例如,在一个复杂的应用中,当一个组件的状态发生变化导致需要更新DOM时,可以使用Promise来管理这个更新过程,将更新DOM的操作放在.then回调函数中,确保在当前宏任务完成后及时更新DOM,并且在更新DOM之前浏览器有机会完成之前的渲染工作,避免不必要的重绘和重流。
  3. 浏览器如何协调异步任务与渲染线程之间的关系

    • 利用事件循环机制:浏览器通过事件循环来协调JavaScript代码的执行和渲染工作。事件循环不断检查调用栈是否为空,如果为空,则从宏任务队列中取出一个任务(如果有)放到调用栈中执行。在每个宏任务执行完后,会清空微任务队列。这样,异步任务(宏任务和微任务)能够在合适的时机执行,而不会阻塞渲染线程。
    • 渲染时机与异步任务调度:浏览器会在JavaScript执行的间隙寻找合适的时机进行渲染。例如,在执行完一个宏任务和微任务队列后,如果没有新的宏任务立即需要执行,浏览器可能会进行一次渲染更新。另外,一些浏览器API(如requestAnimationFrame)可以让开发者将代码插入到浏览器的下一次重绘之前执行,这可以用于优化动画等需要与渲染紧密配合的场景。例如:
      function animate() {
             
      // 进行动画相关的DOM操作
      requestAnimationFrame(animate);
      }
      animate();
      
    • 在这个例子中,requestAnimationFrame函数将animate函数注册为一个在下一次重绘之前执行的任务。这样,animate函数中的DOM操作能够与浏览器的渲染过程同步,保证动画的流畅性。同时,在animate函数内部,可以合理地安排异步任务,如在动画的某个阶段进行网络请求或者更新数据,并且通过事件循环机制,这些异步任务不会干扰动画的正常执行和浏览器的渲染。
相关文章
|
2月前
|
存储 前端开发 开发者
|
1月前
|
前端开发 JavaScript
宏任务和微任务在浏览器渲染过程中的执行顺序
宏任务和微任务是浏览器事件循环中的两种任务类型。宏任务包括整体代码块、setTimeout等,微任务有Promise.then、MutationObserver等。每个宏任务执行完毕后,会先执行完所有微任务,再进行下一轮渲染或执行下一个宏任务。
|
2月前
|
缓存 自然语言处理 前端开发
浏览器渲染
【10月更文挑战第28天】浏览器渲染涉及将HTML、CSS和JavaScript代码转换为可视网页,主要步骤包括:解析HTML构建DOM树、解析CSS构建CSSOM树、合并DOM与CSSOM生成渲染树、布局确定元素位置和尺寸、绘制元素到屏幕、合成图层形成最终图像。此过程不断优化以提升性能。
|
2月前
|
前端开发 JavaScript 异构计算
简述浏览器的渲染原理
浏览器渲染原理主要包括以下步骤:1)解析HTML文档生成DOM树;2)解析CSS生成CSSOM树;3)结合DOM与CSSOM生成渲染树;4)布局计算(回流)确定元素大小和位置;5)绘制(Paint)将节点转为图形内容;6)合成(Composite)多层图像。整个过程从文档解析到最终输出完整网页,并通过优化技术提升性能。
|
7月前
|
缓存 JavaScript 前端开发
浏览器渲染:理解页面加载的幕后工作
浏览器渲染:理解页面加载的幕后工作
|
6月前
|
移动开发 前端开发 JavaScript
浏览器端图表渲染技术SVG, VML HTML Canvas
浏览器端图表渲染技术SVG, VML HTML Canvas
47 0
|
7月前
|
前端开发 JavaScript 数据可视化
探索浏览器的内心世界:渲染机制的奥秘
探索浏览器的内心世界:渲染机制的奥秘
探索浏览器的内心世界:渲染机制的奥秘
|
7月前
|
消息中间件 JavaScript 前端开发
前端秘法进阶篇----这还是我们熟悉的浏览器吗?(浏览器的渲染原理)
前端秘法进阶篇----这还是我们熟悉的浏览器吗?(浏览器的渲染原理)
112 0
|
7月前
|
消息中间件 前端开发 Java
【面试题】前端必修-浏览器的渲染原理
【面试题】前端必修-浏览器的渲染原理
|
Web App开发 存储 监控
浏览器基础原理-安全: 渲染进程-安全沙盒
浏览器基础原理-安全: 渲染进程-安全沙盒
78 0