详解原生JavaScript实现jQuery中AJAX处理的方法

在这篇文章,我使用 Node.js作为后端。没错,这就可以全栈(浏览器和服务器)JS了。Node.js 是很简洁的,我鼓励你能在 Github下载demo,并关注该项目。下面是服务器端的代码:

// app.js
var app = http.createServer(function(req, res){
  if(req.url.indexOf("/scripts/") >= 0){
    render(req.url.slice(1), "application/javascript", httpHandler);
  } else if(req.headers['x-requested-with'] === 'XMLHttpRequest'){
    // Send Ajax response
  } else{
    render('views/index.html', 'text/html', httpHandler);
  }
}

该代码段通过检测请求 URL,确定该app返回的相应内容。如果该请求来自 scripts 目录,那么服务器将返回内容类型(content type)为 application/javascript 的相应文件。如果请求头部的 x-requested-with 被设为 XMLHttpRequest,那么该请求是 Ajax 请求,然后返回相应数据。除了以上两种情况,服务器将会返回 views/index.html。

下面我将会展开上一代码段处理 Ajax 请求的注释部分进行深入讲解。在 Node.js端,我已处理了 render 和 httpHandler 的体力活:

// app.js
function render(path, contentType, fn) {
  fs.readFile(__dirname + '/' + path, 'utf-8', function (err, str) {
    fn(err, str, contentType);
  });
}
var httpHandler = function (err, str, contentType) {
  if (err) {
    res.writeHead(500, {'Content-Type': 'text/plain'});
    res.end('An error has occured: ' + err.message);
  } else {
    res.writeHead(200, {'Content-Type': contentType});
    res.end(str);
  }
};

render 函数异步读取被请求文件的内容。该函数向被作为回调函数的 httpHandler 传递一个引用。
httpHandler 函数检测 error 对象是否存在(如:被请求文件不能被打开,该对象就会存在)。另外,指定类型是好的做法,那么服务器返回的文件内容就会拥有适当的 HTTP 状态码(status code)和内容类型(content type)。

测试 API
让我们为后端API编写一些单元测试,从而确保它们能正确运行。对于这类测试,我会请求 supertest 和 mocha帮助。

// test/app.request.js
it("responds with html", function(done){
  request(app)
    .get("/")
    .expect("Content-Type", /html/)
    .expect(200, done);
});
it('responds with javascript', function (done) {
request(app)
  .get('/scripts/index.js')
  .expect('Content-Type', /javascript/)
  .expect(200, done);
});
it('responds with json', function (done) {
request(app)
  .get('/')
  .set('X-Requested-With', 'XMLHttpRequest')
  .expect('Content-Type', /json/)
  .expect(200, done);
});

这些测试确保了我们的 app 对于不同请求能返回正确的内容类型(content type)和HTTP 状态码(status code)。一旦你安装了这些依赖,那么你就能使用命令 npm test 运行这些测试。

界面
现在,让我们看看用户界面的 HTML 代码:

// views/index.html
<h1>Vanilla Ajax without jQuery</h1>
<button id="retrieve" data-url="/">Retrieve</button>
<p id="results"></p>

上述的 HTML 代码看起来很简洁。没错,正如你所看到的,所有令人兴奋的事情都发生在 JavaScript。

onreadystate vs onload
如果你看过任何一本权威的、关于 Ajax 的书,你可能会发现 onreadystate 在书上随处可见。该回调函数需要通过嵌套的 ifs 或多个 case 语句完成,这使得难以记忆。让我们再次回顾 onreadystate 和 onload 事件。

(function() {
  var retrieve = document.getElementById('retrieve'),
    results = document.getElementById('results'),
    toReadyStateDescription = function(state) {
      switch (state) {
        case 0:
          return 'UNSENT';
        case 1:
          return 'OPENED';
        case 2:
          return 'HEADERS_RECEIVED';
        case 3:
          return 'LOADING';
        case 4:
          return 'DONE';
        default:
          return '';
      }
    };
  retrieve.addEventListener('click', function(e) {
    var oReq = new XMLHttpRequest();
    oReq.onload = function() {
      console.log('Inside the onload event');
    };
    oReq.onreadystatechange = function() {
      console.log('Inside the onreadystatechange ev![此处输入图片的描述][1]ent with readyState: ' +
        toReadyStateDescription(oReq.readyState));
    };
    oReq.open('GET', e.target.dataset.url, true);
    oReq.send();
  });
}());

上述代码会在 控制台(console) 输出以下语句:

onreadystatechange 事件能在请求的任何过程中被触发。如能在每个请求前、请求末。但根据文档,onload 事件只会在请求成功后触发。又因为 onload 事件是一个常见的 API,所以你能在很短时间内掌握它。onreadystatechange 事件可作为后备(原文是backwards compatible 向后兼容?)方案。而 onload 事件应该是你的首选。而且 onload 事件与 jQuery 的 success 回调函数类似,难道不是吗?

###设置请求头部
jQuery 私下帮你设置请求头部了,所以后端能检测这是一个 Ajax 请求。一般来说,后端并不关心 GET 请求是从哪而来,只要能返回正确的响应即可。当你相用同样的 web API 返回 Ajax 或 HTML 时,这就派上用场了。让我们看看如何通过原生 JavaScript 设置请求头部:

var oReq = new XMLHttpRequest();
oReq.open('GET', e.target.dataset.url, true);
oReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
oReq.send();

与此同时,我们在 Node.js 做一个检测:

if (req.headers['x-requested-with'] === 'XMLHttpRequest') {
  res.writeHead(200, {'Content-Type': 'application/json'});
  res.end(JSON.stringify({message: 'Hello World!'}));
}

正如你所看到的,原生 Ajax 是一个灵活且现代化的前端 API。你可以利用请求头部做很多事情,其中一种是版本控制。例如,我想让某个 web API 支持多个版本。但我又不想利用 URL,取而代之的是:通过设置请求头部,使客户端能选择它们想要的版本。所以,我们能这样设置请求头部:

oReq.setRequestHeader('x-vanillaAjaxWithoutjQuery-version', '1.0');

然后,在后端写上相应代码:

if (req.headers['x-requested-with'] === 'XMLHttpRequest' &&
  req.headers['x-vanillaajaxwithoutjquery-version'] === '1.0') {
  // Send Ajax response
}

我们能利用 Node.js 为我们提供的 headers 对象进行相应检测。而唯一需要注意的地方是:以小写字母读取它们。

响应类型
你可能想知道为什么 responseText 返回的是字符串,而不是能被我们操作的普通 JSON(Plain Old JSON)。原来是因为我没有设置合适的 responseType 属性。该 Ajax 属性会很好地告诉前端 API 所期望服务器返回的数据类型。所以,我们要好好利用它:

var oReq = new XMLHttpRequest();
oReq.onload = function (e) {
  results.innerHTML = e.target.response.message;
};
oReq.open('GET', e.target.dataset.url, true);
oReq.responseType = 'json';
oReq.send();

哇,这样我们就不必再对返回的纯文本解析为 JSON 了,我们能告诉 API 我们期待接收的数据类型。该特性几乎得到了所有最新主流浏览器的支持。当然,jQuery 会自动帮我们转为适当的类型。但现在的原生 JavaScript 也具有方便的、完成同样事件的方法。 原生 Ajax 已经支持很多其它响应类型,如 XML。

但遗憾的是,到 IE11 为止,开发团队仍未对 xhr.responseType='json' 进行支持。虽然该特性目前在 Microsoft Edge 得到支持。但这个 Bug 提出几乎两年了。我坚信 Microsoft 团队一直在努力地改进浏览器。让我们期待 Microsoft Edge、aka Project Spartan 当初提出的承诺。
当然,你可以这个解决这个 IE 问题:

oReq.onload = function (e) {
  var xhr = e.target;
  if (xhr.responseType === 'json') {
    results.innerHTML = xhr.response.message;
  } else {
    results.innerHTML = JSON.parse(xhr.responseText).message;
  }
};

避免缓存
对 Ajax 请求进行缓存的浏览器特性都快被我们忘记了。例如,IE 就默认是这样。我还曾因此导致我的 Ajax 不执行而苦恼了几个小时。幸运的是,jQuery 默认清除浏览器缓存。当然,你能在纯 Ajax 达到该目的,而且相当简单:

var bustCache = '?' + new Date().getTime();
oReq.open('GET', e.target.dataset.url + bustCache, true);

查看 jQuery 文档,可知道 jQuery 在每个请求(GET)后面追加一个时间戳作为查询字符串。这在某个程度上让请求变得独一无二,并避免浏览器缓存。每当你触发 HTTP Ajax 请求,你能看到类似如下请求:

OK!这就没有戏剧性的事情发生了。

总结
我希望你能喜欢这篇关于原生 Ajax 的文章。Ajax 在过去某段时间里,被人们看作是一种可怕的怪兽。而事实上,我们已经覆盖了原生 Ajax 所有基础知识。

最后,我会留给你一个简洁的方式进行Ajax调用:

var oReq = new XMLHttpRequest();
oReq.onload = function (e) {
  results.innerHTML = e.target.response.message;
};
oReq.open('GET', e.target.dataset.url + '?' + new Date().getTime(), true);
oReq.responseType = 'json';
oReq.send();
(0)

相关推荐

  • 原生JS封装ajax 传json,str,excel文件上传提交表单(推荐)

    由于项目中需要在提交ajax前设置header信息,jquery的ajax实现不了,我们自己封装几个常用的ajax方法. jQuery的ajax普通封装 var ajaxFn = function(uri, data, cb) { $.ajax({ url: uri, type: 'POST', dataType: 'json', data: data, }) .done(cb) .fail(function() { console.log("error"); }) .always(f

  • 实例讲解使用原生JavaScript处理AJAX请求的方法

    Ajax 是异步的JavaScript和XML的简称,是一种更新页面某部分的机制.它赋予了你从服务器获取数据后,更新页面某部分的权力,从而避免了刷新整个页面.另外,以此方式实现页面局部更新,不仅能有效地打造流畅的用户体验,而且减轻了服务器的负载. 下面是对一个基本的 Ajax 请求进行剖析: var xhr = new XMLHttpRequest(); xhr.open('GET', 'send-ajax-data.php'); xhr.send(null); 在这里, 我们创建了一个能向服务

  • 原生JavaScript实现Ajax的方法

    首先为大家分享了原生JavaScript实现Ajax代码,供大家参考,具体内容如下 var getXmlHttpRequest = function() { if (window.XMLHttpRequest) { //主流浏览器提供了XMLHttpRequest对象 return new XMLHttpRequest(); } else if (window.ActiveXObject) { //低版本的IE浏览器没有提供XMLHttpRequest对象 //所以必须使用IE浏览器的特定实现A

  • 原生js仿jquery实现对Ajax的封装

    前言 与js相比,jquery为我们省去了冗长的获取元素的代码,不用考虑一些麻烦的兼容问题,更加方便的动画实现,以及更加方便的方法调用让我们觉得jquery真是越用越舒服.但是jquery说到底还是对js的封装,我们不光要用的舒服还要深入理解其中的原理,这样才能更好的使用它. 首先我们封装的函数为了能实现可传入无限多个参数,在使用我们即将封装的函数时,需要使用对象进行传参,形式如下: //data作为参数传入我们下面封装的函数 var data = { //数据 user:"yonghu1&qu

  • javascript原生ajax写法分享

    ajax:一种请求数据的方式,不需要刷新整个页面: ajax的技术核心是 XMLHttpRequest 对象: ajax 请求过程:创建 XMLHttpRequest 对象.连接服务器.发送请求.接收响应数据: /** * 得到ajax对象 */ function getajaxHttp() { var xmlHttp; try { //chrome, Firefox, Opera 8.0+, Safari xmlHttp = new XMLHttpRequest(); } catch (e)

  • javascript实现原生ajax的几种方法介绍

    自从javascript有了各种框架之后,比如jquery,使用ajax已经变的相当简单了.但有时候为了追求简洁,可能项目中不需要加载jquery这种庞大的js插件.但又要使用到ajax这种功能该如何办呢?下面和大家分享几种利用javascript实现原生ajax的方法. 实现ajax之前必须要创建一个 XMLHttpRequest 对象.如果不支持创建该对象的浏览器,则需要创建 ActiveXObject,具体方法如下: 复制代码 代码如下: var xmlHttp; function cre

  • 原生 JS Ajax,GET和POST 请求实例代码

    javascript/js的ajax的GET请求代码如下所示: <script type="text/javascript"> /* 创建 XMLHttpRequest 对象 */ var xmlHttp; function GetXmlHttpObject(){ if (window.XMLHttpRequest){ // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest();

  • 原生Javascript封装的一个AJAX函数分享

    最近的工作中涉及到大量的ajax操作,本来该后台做的事也要我来做了.而现在使用的ajax函数是一个后台人员封装的--但他又是基于jquery的ajax,所以离开了jquery这个函数就毫无作用了.而且我觉得,jquery的ajax方法是很完善的了,可以直接用,如果都有jquery了,那么他的ajax就不用白不用了.我缺少的是一个能在没有jquery的情况下使用的ajax方法. 所以我也花一天时间写了一个,参数与调用方法类似于jquery的ajax.就叫xhr吧,因为xhr=XMLHttpRequ

  • JavaScript原生xmlHttp与jquery的ajax方法json数据格式实例

    javascript版本的ajax发送请求 (1).创建XMLHttpRequest对象,这个对象就是ajax请求的核心,是ajax请求和响应的信息载体,单是不同浏览器创建方式不同 (2).请求路径 (3).使用open方法绑定发送请求 (4).使用send() 方法发送请求 (5).获取服务器返回的字符串   xmlhttpRequest.responseText; (6).获取服务端返回的值,以xml对象的形式存储  xmlhttpRequest.responseXML; (7).使用W3C

  • 详解原生JavaScript实现jQuery中AJAX处理的方法

    在这篇文章,我使用 Node.js作为后端.没错,这就可以全栈(浏览器和服务器)JS了.Node.js 是很简洁的,我鼓励你能在 Github下载demo,并关注该项目.下面是服务器端的代码: // app.js var app = http.createServer(function(req, res){ if(req.url.indexOf("/scripts/") >= 0){ render(req.url.slice(1), "application/javas

  • jQuery中ajax的get()方法用法实例

    本文实例讲述了jQuery中ajax的get()方法用法.分享给大家供大家参考.具体分析如下: $.get()通过 HTTP GET请求从服务器上请求数据. 语法结构: 复制代码 代码如下: $.get(url, [data], [callback], [type]); 参数解析: 1.URL:必须,规定请求的URL. 2.data:可选,待发送 Key/value 参数. 3.callback:可选,请求成功后所执行的回调函数. 4.type:可选,返回内容格式,xml, html, scri

  • jQuery中ajax的load()方法用法实例

    本文实例讲述了jQuery中ajax的load()方法用法.分享给大家供大家参考.具体分析如下: 此函数jQuery中简单而功能强大的ajax方法. 它可以从服务器加载内容,然后写入匹配元素. 语法结构: 复制代码 代码如下: $(selector).load(URL,data,callback); 参数解析: 1.selector:一个选择器,可以将内容加载到此选择器匹配的元素中. 2.URL:必须,需要加载的一个url地址. 3.data:可选,与请求一同发送的查询字符串键/值对集合. 4.

  • jQuery中ajax的post()方法用法实例

    本文实例讲述了jQuery中ajax的post()方法用法.分享给大家供大家参考.具体分析如下: $.post() 方法通过HTTP POST请求从服务器上请求数据. 语法结构: 复制代码 代码如下: $.post(URL,data,callback); 参数解析: 1.URL:必须,规定请求的URL. 2.data:可选,规定连同请求发送的数据. 3.callback:可选,规定请求成功后所执行的函数名. 代码实例: 复制代码 代码如下: <!DOCTYPE html> <html&g

  • jQuery中Ajax的load方法详解

    先来看一个Ajax例子 复制代码 代码如下: <!DOCTYPE html> <html> <head lang="en">     <meta charset="UTF-8">     <title></title> </head> <body> <input type="button" value="Ajax提交" onc

  • jquery中ajax跨域方法实例分析

    本文实例分析了jquery中ajax跨域.分享给大家供大家参考,具体如下: JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问 方法一: jsonp之 getJSON js var url = "http://localhost/mytest/jsonp_php.php?callback=?"; $.getJSON(url, { "age": 21, "name

  • 用原生JavaScript实现jQuery的$.getJSON的解决方法

    今天在写一DEMO,其中用到了jQuery的$.getJSON方法,写完后发现整个DEMO中用到jQuery中的就这一个地方,但要引入一个jQuery实在不划算,于是就自己实现了一个简单版的,基本可以满足需求,现分享出来: 复制代码 代码如下: var $ = {    getJSON: function(url, params, callbackFuncName, callback){        var paramsUrl ="",            jsonp = this

  • jquery中AJAX请求 $.post方法的使用

    使用jQuery的$.post方法可以以POST形式向服务器发起AJAX请求.$.post方法是jQuery的实用工具方法. post和get发送方式的特点, GET 方法提交数据不安全,数据置于请求行,客户端地址栏可见; GET 方法提交的数据大小限制在255 个字符之内.POST方法提交的数据置于消息主体内,客户端不可见, POST 方法提交的数据大小没有限制. $.post方法语法 $.post(url,parameters,callback) 参数   url (字符串)服务器端资源地址

  • 详解iOS的UI开发中控制器的创建方法

    控制器的创建 说明:控制器有三种创建方式,下面一一进行说明. 一.第一种创建方式(使用代码直接创建) 1.创建一个空的IOS项目. 2.为项目添加一个控制器类. 3.直接在代理方法中创建一个控制器. 复制代码 代码如下: #import "YYAppDelegate.h" #import "YYViewController.h" @implementation YYAppDelegate - (BOOL)application:(UIApplication *)ap

  • javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】

    本文实例讲述了javascript和 jQuery中的AJAX技术.分享给大家供大家参考,具体如下: 1.什么是AJAX? AJAX即"Asynchronous Javascript And XML"(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新. 传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面.

随机推荐