JS基础与高级应用: 性能优化

在现代Web开发中,性能优化已成为前端工程师必须掌握的核心技能之一。本文从URL输入到页面加载完成的全过程出发,深入分析了HTTP协议的演进、域名解析、代码层面性能优化以及编译与渲染的最佳实践。通过节流、防抖、重复请求合并等具体技术手段,全面提升Web应用的性能表现。本文不仅涵盖了理论知识,还提供了实用的代码示例,帮助读者在实际项目中快速应用这些优化策略。

一、从输入 URL 到页面加载完成都做了什么?

第一步: 从 输入 开始分析

URL 和 URI 的区别

URL: 资源定位符 | URI: 资源标识符 | www.baidu.com - http 协议

http 和 tcp 之间有什么关联和区别?

http 属于应用层协议, tcp 属于传输层协议

关联: http 是基于 tcp 实现连接的。udp 无连接、传输速度快、会丢包。

http 是如何建立连接的? 三次握手和四次挥手

img

HTTP 面向连接, 安全。但是传输速率相较低于 UDP , 每次请求前都需要建立连接。

优化方向: 回合制(session) 多路复用 | 压缩头部空间 | 合并请求-长连接

优化点: http1.0 http1.1 http2.0

HTTP1.0 存在的问题:

  1. 没有办法复用连接 | 1.1 复用连接 (持久连接, connection: keep-alive)
  2. 对头阻塞问题 (Head-of-Line Blocking,简称 HOL 阻塞) (下一个请求必须在前一个请求到达之后才可以进行); 1.1 => pipelining 解决对头阻塞问题

都是解决传输效率问题

HTTP 1.1 => 2.0: 2.0 解决的问题

  1. 头部空间: 协议层消除头部重复部分,利用算法对头信息压缩整合 ( 头部信息索引表 )。
  2. 1.0/1.1 纯文本格式 | 2.0 二进制优化, HTTP2.0 都是用二进制进行传输, 帧的形式。=> 多路复用(复用通路, 无并发限制)

HTTPS => HTTP + SSL协议

优化: 安全性建立导致网络请求加载时间延长。合并请求-长连接

如何使用 HTTP 2.0 ?

第二步: 解析域名

地址转换成 IP: www.baidu.com => xxx.xxx.xxx.xxx | ARP 协议

IP 转成网址: RARP 协议


什么是 HOST? 如何切换 HOST? => 寻址

浏览器的缓存映射 → 系统缓存映射 → 路由器缓存映射 → 运营商缓存映射 → 根服务器

/etc/hosts localhost 127.0.0.1

实际静态文件存放: 机房、云服务站点 => 大流量问题 =>

配置多个 IP 地址、LB负载均衡、云服务

CDN 内容分发网络

缓存机制: 各级缓存 => 浏览器缓存 (304) - 强缓存(expire cache-control) / 协商缓存 last-modify、etag 找服务端进行验证是否需要缓存。

寻址、缓存

········································································································································································

二、代码层面性能优化

并发控制 QPS

  1. 浏览器请求上限 - 最大同时请求 6 条。

img

并发优化: 同时发出 20 条请求,但是由于服务或者业务需求, 我们的性能只能同时处理 3 个, 怎么去做?

分析:

输入: 参数 max - 最大的同时处理量

存储: reqpool - 并发池 (实时更新, 出去一个进来一个)

思路: 执行且回调, 实时加入添加。 执行 => 回调 => 塞入 => 返回 (循环)

js复制代码    class limitPromise {constructor(max){// 异步"并发"上限this._max =  max || 6 // 当前正在执行的任务数量 - 非满载场景this._count = 0// 等待执行的任务队列this._taskQueue = []// 实例 单例模式}// 执行的主入口// caller 执行的请求run(caller) {// 主入口// 输入外部要添加的// 输出返回队列处理的 promisereturn new Promise((resolve, reject)=>{// 创建处理任务const task = this._createTask(caller, resolve, reject)// 当前队列是否拿到上限if(this._count >= this._max){// 超过最大数量, 不去执行, 放入待执行队列中this._taskQueue.push(task)} else {task()}})}_createTask(caller, resolve, reject){return () => {caller().then(res =>{resolve(res)}).catch(err=>{reject(res)}).finally(()=>{this._count--if(this._taskQueue.length){const task = this._taskQueue.shift()task()}})this._count++}}static instance = nullstatic getInstance(max){if(!this.instance){this.instance = new limitPromise(max)}return this.instance}}

节流

js复制代码    function throttle(func, wait) {let timeout = null;let lastExecution = 0;return function (...args) {const context = this;const now = Date.now();if (lastExecution && now < lastExecution + wait) {clearTimeout(timeout);timeout = setTimeout(() => {lastExecution = now;func.apply(context, args);}, wait - (now - lastExecution));} else {lastExecution = now;func.apply(context, args);}};}function handleResize() {console.log('Resize event triggered at', new Date().toLocaleTimeString());}// 创建一个节流函数,最多每1秒执行一次const throttledResize = throttle(handleResize, 1000);// 监听窗口调整大小事件window.addEventListener('resize', throttledResize);

防抖

防抖(Debounce)是指在事件被触发后,等待一段时间再去执行函数。如果在等待时间内事件再次被触发,则重新开始计时。防抖的常见应用场景包括搜索框输入、窗口调整大小、按钮点击等需要防止频繁触发的情况。

防抖函数可以通过 setTimeoutclearTimeout 来实现。以下是一个通用的防抖函数实现:

js复制代码    function debounce(func, wait) {let timeout;return function (...args) {const context = this;clearTimeout(timeout);timeout = setTimeout(() => {func.apply(context, args);}, wait);};}function handleInput() {console.log('Input event triggered at', new Date().toLocaleTimeString());}// 创建一个防抖函数,只有在最后一次输入后等待1秒才执行const debouncedInput = debounce(handleInput, 1000);// 监听输入事件const inputElement = document.querySelector('input');inputElement.addEventListener('input', debouncedInput);

扩展功能:立即执行选项

有时我们希望在事件触发后立即执行一次函数,并在等待时间内不再执行。可以通过增加一个 immediate 参数来实现:

js复制代码    function debounce(func, wait, immediate) {let timeout;return function (...args) {const context = this;const callNow = immediate && !timeout;clearTimeout(timeout);timeout = setTimeout(() => {timeout = null;if (!immediate) func.apply(context, args);}, wait);if (callNow) func.apply(context, args);};}<!---->function handleInput() {console.log('Input event triggered at', new Date().toLocaleTimeString());}// 创建一个防抖函数,在第一次输入时立即执行,之后等待1秒再执行const debouncedInput = debounce(handleInput, 1000, true);// 监听输入事件const inputElement = document.querySelector('input');inputElement.addEventListener('input', debouncedInput);

重复请求的合并

三、编译和渲染优化

打包优化 => 压缩、分割、按需加载、异步加载 => 工程化

渲染优化 => 重排和重绘 => 根据浏览器原理避免

线程阻塞 => JS 后置

内存分配: 即时释放

  1. 对象原则: 层级宜平不宜深, 尽量使用深拷贝(局部), 避免循环利用。
js复制代码<!---->function foo(){course = '' // 永远不会释放this.course = ''}foo()const timeoutId = setTimeout(()=>{}, 1000) // 定时器线程独立于JS线程clearTimeout(timeoutId); // 清除定时器function course{const c = 'xxx'return {c}}const tmp =course()tmp = undefined // 销毁
  1. JS mark & sweep

mark 触达标记: 能够被访问到, 标记; 没有再能访问的 sweep。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/853182.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux驱动学习(九)之中断

一、中断的实现 对于中断的请求&#xff0c;在linux内核中&#xff0c;有一套标准的接口函数&#xff0c;可以实现中断的响应和处理。 #include <linux/interrupt.h>//1 申请中断 static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler…

flask南京市旅游景点信息可视化-计算机毕业设计源码02941

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对南京市旅游景点信息可视化等问题&#xff0…

使用gtest做cpp的单元测试并可查看代码覆盖率

前言 由于工作需要&#xff0c;要使用googletest做单元测试&#xff0c;本文记录下搭建gtest单元测试环境&#xff0c;并查看代码覆盖率的方法&#xff0c;以备不时之需。 准备工作 编译gtest 克隆gtest源码&#xff1a; git clone https://github.com/google/googletest.g…

QUIC 和 TCP: 深入解析为什么 QUIC 更胜一筹

引言 在过去的三十年里&#xff0c;HTTP&#xff08;超文本传输协议&#xff09;一直是互联网的支柱。我们可以通过 HTTP 浏览网页、下载文件、流式传输电影等。这一协议随着时间的推移已经得到了重大改进。 HTTP 协议是一个应用层协议&#xff0c;它基于 TCP&#xff08;传输…

【git使用一】windows下git下载、安装和卸载

目录 &#xff08;1&#xff09;下载安装包 &#xff08;2&#xff09;安装git &#xff08;3&#xff09;安装验证 &#xff08;4&#xff09;卸载git &#xff08;1&#xff09;下载安装包 官网下载地址&#xff1a;Git 国内镜像下载地址&#xff1a;CNPM Binaries Mir…

Unity图集

概述 相信在同学们学习过程中&#xff0c;在UI的的使用时候一定经常听说过图集的概念。 Unity有UI的组件&#xff0c;有同学们好奇&#xff0c;那为什么还要使用图集呢&#xff1f; 这就需要提到一个性能优化的问题了&#xff0c;因为过多的UI图片&#xff0c;会大幅增加Dra…

【机器学习】LightGBM: 优化机器学习的高效梯度提升决策树

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 LightGBM: 优化机器学习的高效梯度提升决策树引言一、LightGBM概览二、核心技术…

buildroot编译出错you should not run configure as root

虚拟机版本&#xff1a;ubuntu-22.04.4 问题 buildroot在图形配置后&#xff0c;执行 sudo make开始编译出现以下错误configure: error: you should not run configure as root (set FOenvironment to bypass this check) 在网上看到说在/etc/profile文件中添加以下内容 exp…

火车头采集织梦发布模块插件下载及教程

火车头采集网页数据发布到织梦CMS&#xff08;DeDeCMS&#xff09;系统操作步骤如下&#xff1a; 1. 火车头采集织梦DeDeCMS发布模块下载安装 百度网盘&#xff1a;火车头采集织梦CMS发布插件下载地址 提取码&#xff1a;414h 2. 在火车头采集软件导入织梦De…

MAC系统下安装VUE

下载node.js 点击链接 选择图片中的稳定版本 安装node.js 打开终端&#xff0c;输入 node -v 和 npm -v 显示如上信息表示安装成功 安装vue脚手架&#x1f527; sudo npm install -g vue/cli查看vue版本 vue -V6. 启动项目 1 采用 图形页面方式 控制台输入&#xff…

MySQL 中 Varchar(50) 和 varchar(500) 区别是什么?

一. 问题描述 我们在设计表结构的时候&#xff0c;设计规范里面有一条如下规则: 对于可变长度的字段&#xff0c;在满足条件的前提下&#xff0c;尽可能使用较短的变长字段长度。 为什么这么规定&#xff1f;我在网上查了一下&#xff0c;主要基于两个方面 基于存储空间的考…

C# Winform 用户控件,扩展控件,自定义控件综合实例

Control类是Windows窗体控件的基类&#xff0c;它提供了在 Windows 窗体应用程序中进行可视显示所需的基础结构&#xff0c;可以通过继承来扩展熟悉的用户控件和现有控件的功能。本列介绍三种不同自定义控件以及怎么创建他们。 自定义控件分类 用户控件&#xff1a;基本控件的…

IT入门知识博客文章大纲第二部分《编程语言》(2/10)

目录 IT入门知识博客文章大纲第二部分《编程语言》 1.引言 2.编程语言概述 2.1 编程语言的发展历程 2.2 编程范式 3.常见的编程语言 3.1 Python 3.2 Java 3.3 C 3.4 JavaScript 3.5 Ruby 4.编程语言的选择 4.1 技术需求 4.2 团队技能 4.3 社区和生态系统 4.4 可…

Python也能“零延迟“通信吗?ZeroMQ带你开启高速模式!

目录 1、零基础入门ZeroMQ 🚀 1.1 ZeroMQ简介与安装 1.2 基础概念:Socket类型详解 1.3 实战演练:Hello World示例 2、深入浅出消息模式 🔌 2.1 请求-应答模式( REQ/REP ) 2.2 发布-订阅模式( PUB/SUB ) 2.3 推送-拉取模式( PUSH/PULL ) 3、Python实战ZeroM…

Aptos Builder Jam 亚洲首站|议程公布,无限畅想 Aptos 生态未来

作为一个新兴的 Layer1 公链&#xff0c;Aptos 自诞生之日起的理想便是 “A Layer 1 for everyone” 当 Web3 深陷熊市阴影之时&#xff0c;Aptos 奋力为开发者找到了全新的技术路径&#xff0c;正有 200 项目正在开发&#xff0c;并且已有大量 DeFi 项目落实部署工作&#xff…

shell文本三剑客 awk 和 grep

awk 前言 AWK是一种优良的文本处理工具。它不仅是 Linux中也是任何环境中现有的功能最强大的数据处理引擎之一。 Linux中最常用的文本处理工具有grep&#xff0c;sed&#xff0c;awk。行内将之称为文本三剑客&#xff0c;就功能量和效率来看&#xff0c;awk是当之无愧的文本三…

强化学习-tutorial

强化学习 当你发现收集有标注的数据困难&#xff0c;正确答案人类也不知道是什么的时候&#xff0c;往往是考虑使用RL的时候。尽管机器不知道答案是什么&#xff0c;但是机器会知道什么好&#xff0c;什么不好&#xff0c;通过与环境互动获得奖励。 过程 演算法解RL问题&…

【C++进阶】模板进阶与仿函数:C++编程中的泛型与函数式编程思想

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;栈和队列相关知识 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀模板进阶 &#x1f9e9;<&…

C语言概述与历史

引言 C语言是一门历史悠久且影响深远的编程语言。它不仅为后继的许多编程语言奠定了基础&#xff0c;同时因其高效性和灵活性在系统编程和嵌入式开发领域得到了广泛应用。本篇文章将全面介绍C语言的起源与发展、设计目标与理念&#xff0c;以及C语言的标准演化历程&#xff0c;…

MySQL Online DDL原理解读

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…