对Ajax更细致的理解

最近开始离开JS核心,研习JS的一些具体应用,主要是client-side,包括事件处理模型,异步处理等。本文进入Ajax的研习,在学习的过程中,下意识的尝试总结一种快速掌握一项应用技术的理论和方法——一种学习理论,利用Ajax作为一种特殊例子,找到有关理论、技术、任务和方案之间的原理。文未略译《Basic AJAX Request: XMLHttpRequest》,作为Ajax技术的HOWTO。

Ajax很流行,它指代什么?

Ajax,一个前端开发社区人尽皆知的技术名词,一个曾经被誉为推动Web进入新时代的关键技术,然而了解的人知道,Ajax不是个单一技术概念,它是一集相关技术的概括;随着HTML5,CSS3和JS的演化,Ajax有一点点昨日黄花的感觉,至少就Ajax这个字面,很早就outdate了。不过,Ajax所针对的问题,所完成的任务并没有过时,在当下流行的单页面程序中,Ajax所指代的任务依然重要,历久弥新。

Ajax的一般理解

Ajax是典型的用【技术】概述【任务】的例子,任务历时不变,但技术却一直在变,所以Ajax这个名字很早就不能指示任务。然,Ajax所指代的任务确切是什么任务呢?它有一集技术,来完成这个任务,又包括哪些技术呢?

用什么概述Ajax完成的任务呢?

Ajax所指代的或者完成的任务,最一致的看法是,在不刷新页面的情况下与服务器进行数据交换,目的是为丰富页面的功能。这个普识的表述是很直观易懂的,但是它非常的“高层”,忽略了很多细节。

Ajax涵盖了哪些技术?

而Ajax所指代的一集技术,一般认为涵盖了以五种:

  • HTML (or XHTML) and CSS for presentation
  • The Document Object Model (DOM) for dynamic display of and interaction with data
  • JSON or XML for the interchange of data, and XSLT for its manipulation
  • The XMLHttpRequest object for asynchronous communication
  • JavaScript to bring these technologies together

以上是对Ajax指代的任务和技术的一般理解,然而作一个专业的的评价,参与如下的标准:

所谓专业,就是对自己所使用的工具(技术),和负责的任务有特别细致的理解。

以上对Ajax的表述还不够细致,也就是说,如果你只停留在上面的理角层面,就Ajax而言,你还不是很专业。

有关于技术和任务的理论

要变得专业,我们需要一种理论指导。

复杂的任务与复杂的技术

其实,一项「有用」的事务,它的任务和所需技术都是多元的,不会非常纯一。也就是说,一项复杂任务(复杂结构的成品)可能会被分割多个「相似」甚至「性质不同」的子任务,例如一支web程序会有界面构建与交互,界面布局设计,网络传输等任务。我们学习的一个侧面,就是去标识这些任务,并掌握对应的技术。

精通有用技术的障碍

而阻碍我们精通一项技术,成为该项任务的专家的,主要有以下几项:

第一,复杂任务内的多个子任务交叉在一起,难以分别;

第二,技术本身具有某种逻辑层次,掌握低层技术比较困难,但是又异常重要;理解高级技术需要基础,而基础掌握越牢越专业;

第三,新技术/任务会引入新的自然属性,需要新的认知努力,例如Ajax有数据交换格式新属性,和HTTP自然属性;

Ajax更专业细致的理解

就Ajax而言,它的技术性和任务,和Event处理、DOM操作等交织在一起——网络数据交换请求事件完成后,更新DOM。但显然,三个技术有质的区别,分别完成不同的编程任务。Ajax的核心应该只是(异步)网络数据交换,是一般网页HTTP请求的特殊利用,我们看这个图:

[caption id="attachment_715" align="aligncenter" width="513"] ajax与微HTTP数据交换 ajax与微HTTP数据交换[/caption]

这个图里,我们划定了Ajax有两项核心技术:XHR(一个提供HTTP传输功能的BOM对象)和数据格式。像Event处理、DOM操作等这些属于相关技术(任务),一些扰乱我们思考的“障碍”。

第二个“障碍” 是,这些核心技术是很“高级”的,需要理解的基础。例如,XHR其实是一个提供HTTP传输功能的BOM对象,BOM对象是对JS对象的应用,像DOM,EVENT都是JS对象的应用。这就需要我们对JS有更扎实的专业基础;

由此,我们得到对Ajax更进一步细致的理解:

  • 第一,Ajax任务可以叫「微HTTP数据交换」任务;
  • 第二,Ajax技术核心是XHR(一个提供HTTP传输功能的BOM对象)和数据格式;

原生Ajax的实例

作为前端开发者,他们有一些常规的任务,这也是他们的职责所在和能力体现。而在完成这些常规任务时,他们很多人都是使用中间的库(library)或者框架(framework),因为易用,他们很少甚至从不知道「库」背后的原生API。这也是为什么我写关事件委托( How JavaScript Event Delegation Works)和HTTP请求(Do a Basic HTTP Request with Node.js,)文章的原因,本文是第三种常规任务——一个原生的AJAX例子。

第一,取得XHR对象实例

无论需要怎样的微HTTP数据交换,在准备好其他数据后,数据交换的第一步,是取得一个XMLHttpRequest对象实例。以下是一个早期的例子(现在对IE的判断可以忽略):

var request;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
  request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
  try {
    request = new ActiveXObject('Msxml2.XMLHTTP');
  } 
  catch (e) {
    try {
      request = new ActiveXObject('Microsoft.XMLHTTP');
    } 
    catch (e) {}
  }
}

嗯,是不是很复杂?这是你活在库或框架背后真实场景,原生真正面目。

第二,配置XHR并发出交换请求

在取得XHR对象实例后,我们需要对其进行配置,根据不同「数据交换任务」来配置,这一部分需要有HTTP请求模型的知识基础。最简单的HTTP交换任务是GET查询——使用少量甚至没有额外数据来请求一个资源。例如如下一个最简单GET查询的配置并触发:

request.open('GET', 'https://davidwalsh.name/ajax-endpoint', true);
request.send(null);

open方法配置了请求类型(GET,POST或其它),和请求的资源目标。如果请求类型是POST的方法,在触发调用前(send方法),我们可能需要先配置HTTP HEADER来指定请求体(request body)的格式:

request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

第三,处理服务器响应

当然,光发出交换请求只完成了一半,我们还要处理服务器响应。XHR(XHR2)有多个事件API给我们编程,安装相应的事件处理程序。注意XHR事件处理安装属于「配置任务」,配置要在触发(send方法)之前,虽然异步执行会在后。有两种安装方法:

/ state changes
request.onreadystatechange = function() {
  if(request.readyState === 4) { // done
    if(request.status === 200) { // complete	
      console.log(request.responseText)
    }
  }
};

// addEventListener
function callbackFn(e) {
  // Handle each event
}
request.addEventListener("progress", callbackFn, false);
request.addEventListener("load", callbackFn, false);
request.addEventListener("error", callbackFn, false);
request.addEventListener("abort", callbackFn, false);

你可任选一种,不过优先选用更现代更优雅的addEventListener 方式。

这里,我们用了最简单的例子介绍完了XMLHttpRequest 原生API使用方式,如果你需要更复杂的AJAX任务,例如交换一个表单数据,可以查阅MDN( Mozilla Developer Network)文档。

参考

裸男
Nakeman.cn 2023 Build by Gatsby and Tailwind, Deploy on Netlify.