今天看了不少文章,比较感兴趣的是 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 = new XMLHttpRequest();
} else if (window.ActiveXObject) {
try {
request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch (e) {
try {
request = new ActiveXObject('Microsoft.XMLHTTP');
}
catch (e) {}
}
}
request.onreadstatechange = function(){
// handle data;
};
request.open('GET', 'http://barretlee.com/test.json', true);
request.send(null);

而使用 Fetch API,我们只需要:

fetch('http://barretlee.com/test.json').then(function(response) {
// Convert to JSON
return response.json();
}).then(function(val) {
console.log(val);
});

对于 Text/HTML 和 Blob 等格式的请求和转化也是异常方便:

// Text/HTML 请求
fetch('/next/page').then(function(response) {
return response.text();
}).then(function(text) {
console.log(text);
}); // Blob 流
fetch('flowers.jpg').then(function(response) {
return response.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(new Response(“Hi, Barret Lee”));
});

demo.html 的回调中使用 Fetch 获取/test/a.html 这个并不存在的内容,被 ServiceWorker 捕获,交给 worker.js 处理并响应 Hi, Barret Lee 的文本,整个设计思路十分清晰,很轻松地拦截了来自客户端的请求,并作出了响应。

由于 ServiceWorker 是对 Promise 友好的,响应时也可以模拟服务器休眠状态:

addEventListener("fetch", function(evt) {
evt.respondWith(new Promise(function(resolve, reject){
setTimeout(function(){
resolve(new Response(“Hi, Barret Lee”));
}, 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 提供的文档中深入学习下。

本文转自我的 个人博客,原文链接:http://www.barretlee.com/blog/2016/02/16/when-fe-has-the-power-of-server/

☞ 参与评论

拓展阅读

当前端也拥有 Server 的能力的更多相关文章

  1. 一名小小的SQL Server DBA想谈一下SQL Server的能力

    一名小小的SQL Server DBA想谈一下SQL Server的能力 百度上暂时还没有搜索到相关的个人写的比较有价值的文章,至少在中文网络的世界里面没有 但是在微软的网站有这样一篇文章:<比 ...

  2. YUI前端优化之Server篇

    二.网站Server 篇:使用内容分发网络为文件头指定Expires或Cache-ControlGzip压缩文件内容配置ETag尽早刷新输出缓冲使用GET来完成AJAX请求 11.使用内容分发网络 用 ...

  3. [转] Web前端优化之 Server篇

    原文链接: http://lunax.info/archives/3093.html Web 前端优化最佳实践第二部分面向 Server .目前共计有 6 条实践规则.[注,这最多算技术笔记,查看最原 ...

  4. 转载: SQL Server中的索引

    http://www.blogjava.net/wangdetian168/archive/2011/03/07/347192.html 1 SQL Server中的索引 索引是与表或视图关联的磁盘上 ...

  5. 【大前端攻城狮之路】JavaScript函数式编程

    转眼之间已入五月,自己毕业也马上有三年了.大学计算机系的同学大多都在北京混迹,大家为了升职加薪,娶媳妇买房,熬夜加班跟上线,出差pk脑残客户.同学聚会时有不少兄弟已经体重飙升,开始关注13号地铁线上铺 ...

  6. 听说尤雨溪在开发vue4.0?是谁煽动了前端圈的焦虑情绪

    导火索因P图而起 今天前端圈里被一张P图搞得好热闹,最初只是QQ群里一个冒名尤雨溪的前端网友发了一句调侃的话,原话截图如下: 看完觉得好搞笑,说尤雨溪在开发vue4.0,有谁学不动了,就给他发10块钱 ...

  7. 006_饿了么大前端总监sofish帮你理清前端工程师及大前端团队的成长问题!

    作者|Sofish编辑|小智 & 尾尾本文是前端之巅向 sofish 的约稿<什么样的人可以称为架构师?>.采访< 饿了么大前端团队究竟是如何落地和管理的?>以及 so ...

  8. 学web前端一定要这样学,不然学完找不到工作哭都来不及!

    因为工作原因,经常关注有关互联网行业的最新动态.这不,刚送走了高考,又迎来了每年的毕业季,看到好多人都说今年的前端工作不好找,很多童鞋简历投了一大堆,也没有回应,发现连实习的机会都没有,好不容易去面试 ...

  9. HTTP/2 Server Push 详解(上)

    收录待用,修改转载已取得腾讯云授权 译者:TAT.Johnny 原文:https://www.smashingmagazine.com/2017/04/guide-http2-server-push/ ...

随机推荐

  1. Javascript生成二维码(QR)

    网络上已经有非常多的二维码编码和解码工具和代码,很多都是服务器端的,也就是说需要一台服务器才能提供二维码的生成.本着对服务器性能的考虑,这种小事情都让服务器去做,感觉对不住服务器,尤其是对于大流量的网 ...

  2. WCF学习之旅—第三个示例之四(三十)

           上接WCF学习之旅—第三个示例之一(二十七)               WCF学习之旅—第三个示例之二(二十八)              WCF学习之旅—第三个示例之三(二十九)   ...

  3. 【Win 10 应用开发】在App所在的进程中执行后台任务

    在以往版本中,后台任务都是以独立的专用进程来运行,因此,定义后台任务代码的类型都要位于 Windows 运行时组件项目中. 不过,在14393中,SDK 作了相应的扩展,不仅支持以前的独立进程中运行后 ...

  4. VisualStudio2013 如何打开之前版本开发的(.vdproj )安装项目

    当你的项目使用早于 visualstudio2013 的版本开发并且使用 Visual Studio Installer 制作安装项目时,在升级至 VS2013 后会发现新安装项目无法打开, VS20 ...

  5. Mysql事务探索及其在Django中的实践(一)

    前言 很早就有想开始写博客的想法,一方面是对自己近期所学知识的一些总结.沉淀,方便以后对过去的知识进行梳理.追溯,一方面也希望能通过博客来认识更多相同技术圈的朋友.所幸近期通过了博客园的申请,那么今天 ...

  6. HTML块级元素

    前面的话   在HTML5出现之前,人们一般把元素分为块级.内联和内联块元素.本文将详细介绍HTML块级元素 h   标题(Heading)元素有六个不同的级别,<h1>是最高级的,而&l ...

  7. [.NET] C# 知识回顾 - 事件入门

    C# 知识回顾 - 事件入门 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6057301.html 序 之前通过<C# 知识回顾 - 委托 de ...

  8. shiro权限管理框架与springmvc整合

    shiro是apache下的一个项目,和spring security类似,用于用户权限的管理‘ 但从易用性和学习成本上考虑,shiro更具优势,同时shiro支持和很多接口集成 用户及权限管理是众多 ...

  9. JS继承之借用构造函数继承和组合继承

    根据少一点套路,多一点真诚这个原则,继续学习. 借用构造函数继承 在解决原型中包含引用类型值所带来问题的过程中,开发人员开始使用一种叫做借用构造函数(constructor stealing)的技术( ...

  10. Struts2实现ajax的两种方式

    基于Struts2框架下实现Ajax有两种方式,第一种是原声的方式,另外一种是struts2自带的一个插件. js部分调用方式是一样的: JS代码: function testAjax() { var ...