Why's THE Design(为什么这么设计) 是一系列关于计算机领域程序设计决策的文章(偏向于前端领域),在该系列会从不同的角度讨论这种设计的优缺点、对具体实现造成的影响。由 Draveness 的《为什么这么设计》 启发
正文
在阅读本文之前,需要大家先忘掉类似于 $.ajax()
和 axios
这类的库方法或库,回归到最原始的 XMLHttpRequest
,然后再去思考新设计的 fetch API
。因此阅读本文之前,你需要一些简单的前置知识:XMLHttpRequest
(后面以 XHR
简称) 和 fetch API
。
首先,我们给两个概念下一个定义。XHR
和 fetch API
都是浏览器给上层使用者暴露出来的 API(类似于操作系统暴露系统 API 给浏览器这类应用一样)。这两套暴露的 API 给上层使用者提供了部分操作 http 包的能力。换句话说,这两者都是建立在 http 协议上的,我们可以将其当成具有部分功能的 http 客户端。
XHR
出现时间很早,最开始在 Microsoft Exchange Server 2000 的 Outlook Web Access 中引入,随后在 1999 年加入到 IE5 中,最后所有主流的浏览器都引入了该特性。也就是说,XHR
已经 21 岁高龄了(一种技术能存活如此之久,足够证明其经典)。而 XHR
变得人尽皆知则是由于 AJAX 架构的出现(在这里需要提到的是,Ajax 更多的被认为是一种 Web 应用架构,其最早出现在 Jesse James Carrett 于 2005年 发表的一篇 《Ajax: A New Approach to Web Applications》),各种著名应用都使用了 AJAX(比如 Google 的 Gmail)。不管是谁促进了谁,都足以证明 XHR
解决了当时很大的痛点问题,减少网络延迟或损耗,提高用户体验,并增强了 JavaScript 在浏览器上操作 HTTP 的能力。
用技术术语来讲,XHR
在当时很好的解决了客户端和服务器端的异步通信。我们想象下当时的状况,Web 体系增长很快,但web 应用的功能仍然是相对简单的,更多是对信息的展示,因此 XHR
设计者无需考虑过多的架构设计(仔细思考一下,当时没有硬需求,而且过度设计同样是个问题)。
以现代软件工程的角度来看,XHR
的整个设计非常混乱,将 request、response 和事件监听混在一个对象里,并且需要通过实例化才能够发送请求(后面我们通过实际代码来演示)。这带来的问题是在实际使用过程中配置和调用方式没有组织和可维护性(注意,这在 web 应用比较简单的时候不构成问题)。用架构的术语来讲,XHR 不符合关注点分离原则(SOC),SOC 原则期望在设计系统时候能够将系统元素分离开来,尽量保持各个元素的职责单一(比如 TCP/IP 协议簇的分层、经典 MVC 架构都是 SOC 原则的经典体现)。
我们来看一下最原始的 XHR
的使用:
let xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';
xhr.onload = function() {
console.log(xhr.response);
}
xhr.onerror = function() {
console.log('error');
}
xhr.send();
复制代码
从上面代码可以很明显的看出,http request 、http response 和事件监听都处于同一个 xhr
实例里面。整个代码组织缺少语义化,并且可能陷入回调地狱的窘境。如果没有各种包装库的实现(这也同样是 fetch
API 出现后难以推广的原因之一,因为库封装的很好),手写 xhr
绝对是个痛苦的事情。
按照 jake archibald(Google chrome 成员,个人比较喜欢的一个技术专家 ) 的话来讲:
XHR was an ugly baby and time has not been kind to it. It's 16 now. In a few years it'll be old enough to drink, and it's enough of a pain in the arse when it's sober
从近二十年的历史来看,Web 绝对是世界的中心(你看 JavaScript 设计得这么潦草的语言仍然占据很重要地位就可以侧面理解这句话的含义了)。Web 的发展代表着用户群体增多,也就意味着各种需求的增多(比如由文本传递到各种多媒体信息传递),各种技术方案、标准不断被引入到 Web 体系中(比如著名的 WHATWG 组织和 ECMA International 组织),XHR
显然到