当前端也拥有 Server 的能力(前端功能实现)
liuian 2025-06-09 23:33 4 浏览
今天看了不少文章,比较感兴趣的是 Cache API。它是浏览器 Request/Response 的缓存管理工具,其使用风格和运用场景让我瞬间联想到了 ServiceWorker 和 Fetch API,相信很多同学也多次看到过这两个东西,本文会对它们做一个简洁的介绍,并谈一谈我对这些新玩具的看法。
Fetch API
传统的 XMLHttpRequest,出了两个版本,在 XHR2.0 中引入了跨源请求、上传进度事件和对二进制数据的支持等,这些 API 的增强让 AJAX 可以很方便地与 HTML5 API 相结合,例如 File System API、Web Audio API、WebGL 等,让前端对音视频的处理和富客户端元素的处理更加有亲和力。
作为一个与后端交互的通道,XHR2.0 的接口封装依然过于底层。看看 jQuery 对 AJAX 的封装,再回头看看我们今天要介绍的 Fetch API,不得不惊叹,浏览器已经在应用层面思考着功能的拓展,依托着 Promise 产出了十分友好的新一套接口。
以前我们使用 XHR 去请求一个资源,会这么做:
// Just getting XHR is a mess!
if(window.XMLHttpRequest){
request=newXMLHttpRequest;
}elseif(window.ActiveXObject){
try{
request=newActiveXObject('Msxml2.XMLHTTP');
}
catch(e){
try{
request=newActiveXObject('Microsoft.XMLHTTP');
}
catch(e){}
}
}
request.onreadstatechange=function{
// handle data;
};
request.open('GET','http://barretlee.com/test.json',true);
request.send;
而使用 Fetch API,我们只需要:
fetch('http://barretlee.com/test.json').then(function(response){
// Convert to JSON
returnresponse.json;
}).then(function(val){
console.log(val);
});
对于 Text/HTML 和 Blob 等格式的请求和转化也是异常方便:
// Text/HTML 请求
fetch('/next/page').then(function(response){
returnresponse.text;
}).then(function(text){
console.log(text);
});
// Blob 流
fetch('flowers.jpg').then(function(response){
returnresponse.blob;
}).then(function(blob){
document.querySelector('img').src=URL.createObjectURL(blob);
});
Fetch API 让我们更加关注请求和响应之间的交互,而不是聚焦在如何请求和如何处理响应两个问题上。
当然,它也存在几个相比 XHR 不足的地方,首先它不能 abort 请求,同时也不能获取请求过程中的 progress 状态,当然也没有 timeout 超时处理。Fetch API 是基于 Promise 的,而 Promise 的状态只有 pending、resolve、reject,不会出现诸如 pending(80%) 的状态提示;我们也无法对一个 Promise chains 做 abort 处理,这些都是能够理解并且接受的。
我也相信,Fetch API 有能力提供这些状态信息和附加的 API,只是在这个不成熟的环境下,它目前不需要迈这么大的步子。
ServiceWorker
ServiceWorker,简单而言就是一个放在前端的 HTTP 拦截器,比如我们要请求一个不存在的 URI 如:/test/a.html,直接请求就会响应 404,而如果我们预先在 ServiceWorker 中注册了这个地址,并且指定响应内容,当再次请求时,你会看到结果是存在的,举个例子:
<!—demo.html—>
<script>
navigator.serviceWorker.register("worker.js",{
scope:”/test/a.html"
}).then(function{
fetch(‘/test/a.html’).then(function(response) {
return response.text;
}).then(function(text) {
console.log(text);
});
});
</script>
在 demo.html 文件中,我们看到,将 /test/a.html 的请求交给 worker.js 来处理,处理方式为:
// workker.js
addEventListener("fetch",function(evt){
evt.respondWith(newResponse(“Hi,BarretLee”));
});
在 demo.html 的回调中使用 Fetch 获取/test/a.html 这个并不存在的内容,被 ServiceWorker 捕获,交给 worker.js 处理并响应 Hi, Barret Lee 的文本,整个设计思路十分清晰,很轻松地拦截了来自客户端的请求,并作出了响应。
由于 ServiceWorker 是对 Promise 友好的,响应时也可以模拟服务器休眠状态:
addEventListener("fetch",function(evt){
evt.respondWith(newPromise(function(resolve,reject){
setTimeout(function{
resolve(newResponse(“Hi,BarretLee”));
},1000);
}));
});
由于 Fetch API 提供了对 Header 头的修改,我们几乎可以利用 ServiceWorker 实现真实 HTTP Server 的基本功能。
ServiceWorker 一定程度上改变了 Web 协作的交互模式,传统情况下,我们需要开启一个 Web Server,或者让其他人提供 HTTP Server,前后端之间交互,沟通成本比较高。而 ServiceWorker 把 HTTP Server 搬到了客户端,我们可以在浏览器上轻松 Hold 住两端的操作。这也算是 Web 技术栈融合的表现吧。
当我们的目光放在 HTTP 的交互上,ServiceWorker 会有无限的想象空间,比如对 History API 的延伸思考,跨页面共享问题,前端请求合并和分拆问题,mock 数据问题,前后端的联调问题,类 graphQL 问题,数据的缓存更新和复用问题等等。
Cache API
Cache API,简而言之就是一个 Request/Response 的缓存对象组,它的生命周期跟 ServiceWorker 是紧密相连的,它没有失效时间,不删除就会一直保持原样。
caches.open('test-cache').then(function(cache){
cache.add('/index.html');
});
一个简单的操作,就将 /index.html 这个页面缓存了下来,如果你使用的是最新版的 Chrome,可以打开 DevTools > Resources > Cache Storage,多了一个 test-cache 的缓存表,表中多出一项,Request 为
http://barretlee.com/index.html, Response 为 OK。如下方式可以查看缓存内容:
caches.open('test-cache').then(function(cache){
cache.keys.then(function(cachedRequests){
console.log(cachedRequests);
});
});
当浏览器处于 idle(空闲) 状态的时候,会将 Cache 资源预加载到本地。这也让我想起了 link 标签中有一个 prefetch 功能,也会有同学想到 Manifest,不过这两个东西都是不能友好控制的,而 Cache 给我们带来了这样的便利。
小结
我一直相当看好 Fetch API 系列相关的新接口,它的特点也很清晰,首先是基于 Promise 的实现,这个实现解决了回调和状态控制的问题,然后是提供了应用级别的接口访问,现在可以把一个 HTTP 请求作为可控的对象随意操作,无论是 Request 还是 Response 都在我们的掌握之中,同时也一定程度解决了跨页面资源共享的问题(至于跨页面通讯,我们有 postMessage 和 MessageChannel 等工具)。
目前浏览器对 Fetch API 和 ServiceWorker 的支持都是比较可观的,虽然 W3C 上的文档状态还是 Draft 模式,相信随着我们对业务需求的更加明确,对前端认知的的不断深入,这些东西将很快被定为 RFC。
本文没有对 API 的使用做深入的说明,一方面是因为这些东西能在 Google 上找到,其次,我觉得有些 API 的设计上还不够成熟,今后会有增删,感兴趣的同学可以去 W3C 提供的文档中深入学习下。
在线观视频学习请关注次微博号
微信号:网页设计自学平台
英文ID:WEB_wysj
长按二维码订阅《网页设计自学平台》
↓↓↓
相关推荐
- WebRTC的拥塞控制技术(Congestion Control)
-
\1.概述对于共享网络资源的各类应用来说,拥塞控制技术的使用有利于提高带宽利用率,同时也使得终端用户在使用网络时能够获得更好的体验。在协议层面上拥塞控制是TCP的一个重要的组成部分;但是对于非面向...
- 当前端也拥有 Server 的能力(前端功能实现)
-
今天看了不少文章,比较感兴趣的是CacheAPI。它是浏览器Request/Response的缓存管理工具,其使用风格和运用场景让我瞬间联想到了ServiceWorker和FetchA...
- Node 如何在 Controller 层进行数据校验
-
作者:山月行转发链接:https://mp.weixin.qq.com/s/UAU_Vpu3o53zqEAKDYgvQQ前言幽默风趣的后端程序员一般自嘲为CURDBoy。CURD,也就是对某一存...
- JWT深度解析:现代Web身份验证的通行证-优雅草卓伊凡
-
JWT深度解析:现代Web身份验证的通行证为什么现在都是JWT为什么要restful-优雅草卓伊凡一、JWT的本质与构成1.1JWT的定义解析JWT(JSONWebToken)是一种开放标准(R...
- Expo SDK 53.0.7 的 超详细 app.json 和 eas.json 配置项说明
-
以下是针对ExpoSDK53.0.7的超详细app.json和eas.json配置项说明,包含所有可能的配置项和实际用例:app.json完整配置手册(ExpoSDK53){...
- 搞懂JSON Schema:给数据加个“身份证”,不再“乱七八糟”!
-
JSON以其简洁、易读的特性广受欢迎,但当数据变得庞大、复杂,或者需要与多人协作时,你是不是也遇到过这些烦恼:“前端传来的数据格式不对,导致后端报错了!”“我的API文档写了一大堆,但别人还是不清楚数...
- W3C 发布 WebAssembly 2.0 工作草案
-
4月20日,W3C公布了WebAssembly2.0的第一批公共工作草案。该草案由3部分组成,分别是:WebAssemblyCoreSpecification–Version...
- ECMAScript标准制定过程展示及ES7新特性披露
-
2015年6正式发布的ES6是ECMAScript的最新版本,它的发布具有里程碑意义,不仅带来了众多的新特性,而且自此将改变ECMAScript的发布策略。本文将会介绍ECMAScript标准的最新...
- 微信小程序云开发教室预约系统的前后端交互与数据库设计
-
需求描述:需要申请使用教室时,可点击教室申请查看教室的使用状况及相关设备。确定好需要的教室后,按学期、校区、教学楼、周次、星期、节次、等维度筛选,并备注用途。例如:当我点击该教室申请占用后,该教室状态...
- 微软推出ManifoldJS,Web App自动转成各平台本地App
-
微软推出开源工具ManifoldJS,可以自动将WebApp转换成各种平台的App(安卓、iOS、ChromeOS、Windows)。ManifoldJS通过获取网站meta-data信息,即可产...
- 听说你需要一个云笔记,正好我们做了一个
-
一星期前,我只是想看看大家是不是有同样的需求,于是我发了一篇《听说你需要一个云笔记,正好我们这里有一个》。结果到了第二天,这个当时只有README.md的项目,已经有好多的Star。后来,想了想这个A...
- RK3588-HDMIRX(瑞芯微rk3588芯片手册)
-
1.简介专栏总目录HDMIIN功能可以通过桥接芯片的方式实现,将HDMI信号转换成MIPI信号接收,RK3588芯片平台自带HDMIRX模块,可以直接接收HDMI信号。本篇文章主要介绍在RK3...
- 分享一个功能强大的Android日志库XLog
-
XLog是什么腾讯开源的Mars项目中有个XLog日志库。XLog是一个高性能文本存储方案,在真实环境中经受了微信数亿级别的考验,具有很好的稳定性。由于其是使用C语言来实现的,故有占用性能、内存小,存...
- Android系统基础(05) Android系统源码 调试
-
adbshell后面跟的命令主要来自:源码\system\core\toolbox目录和源码\frameworks\base\cmds目录。1adb命令@1常用命令adbget-prod...
- Python与Appium实现自动化测试(python3 appium移动端自动化)
-
目录1.什么是Appium2.启动一个app自动化程序的步骤3.appium服务介绍4.appium客户端使用5.adb的使用6.Appium启动过程分析1.什么是Appiumappium是一个开源...
- 一周热门
-
-
Python实现人事自动打卡,再也不会被批评
-
Psutil + Flask + Pyecharts + Bootstrap 开发动态可视化系统监控
-
【验证码逆向专栏】vaptcha 手势验证码逆向分析
-
一个解决支持HTML/CSS/JS网页转PDF(高质量)的终极解决方案
-
再见Swagger UI 国人开源了一款超好用的 API 文档生成框架,真香
-
网页转成pdf文件的经验分享 网页转成pdf文件的经验分享怎么弄
-
C++ std::vector 简介
-
python使用fitz模块提取pdf中的图片
-
《人人译客》如何规划你的移动电商网站(2)
-
Jupyterhub安装教程 jupyter怎么安装包
-
- 最近发表
-
- WebRTC的拥塞控制技术(Congestion Control)
- 当前端也拥有 Server 的能力(前端功能实现)
- Node 如何在 Controller 层进行数据校验
- JWT深度解析:现代Web身份验证的通行证-优雅草卓伊凡
- Expo SDK 53.0.7 的 超详细 app.json 和 eas.json 配置项说明
- 搞懂JSON Schema:给数据加个“身份证”,不再“乱七八糟”!
- W3C 发布 WebAssembly 2.0 工作草案
- ECMAScript标准制定过程展示及ES7新特性披露
- 微信小程序云开发教室预约系统的前后端交互与数据库设计
- 微软推出ManifoldJS,Web App自动转成各平台本地App
- 标签列表
-
- python判断字典是否为空 (50)
- crontab每周一执行 (48)
- aes和des区别 (43)
- bash脚本和shell脚本的区别 (35)
- canvas库 (33)
- dataframe筛选满足条件的行 (35)
- gitlab日志 (33)
- lua xpcall (36)
- blob转json (33)
- python判断是否在列表中 (34)
- python html转pdf (36)
- 安装指定版本npm (37)
- idea搜索jar包内容 (33)
- css鼠标悬停出现隐藏的文字 (34)
- linux nacos启动命令 (33)
- gitlab 日志 (36)
- adb pull (37)
- table.render (33)
- uniapp textarea (33)
- python判断元素在不在列表里 (34)
- python 字典删除元素 (34)
- vscode切换git分支 (35)
- python bytes转16进制 (35)
- grep前后几行 (34)
- hashmap转list (35)