欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一篇搞懂Ajax

程序员文章站 2024-02-04 08:13:28
...

概况

AJAX即“Asynchronous JavaScript and XML”(异步的JavaScriptXML技术),指的是一套综合了多项技术的浏览器网页开发技术。
——*
Ajax是一种通过异步的方式从服务器获取数据而无需卸载当前页面的技术,通过XMLHttpRequest对象的一系列属性和方法与服务器交换数据。在Ajax出现之前使用以下替代方案:

  • 提交至iframe方案
  • JSONP方案:客户端通过script标签的src属性发送接口请求,服务端返回JS形式的数据内容,客户端通过执行约定的函数获取数据。缺点是只能发送GET请求,复杂数据无法提交,且返回的数据内容必须确保被JS正确执行。

Ajax具有以下优势:

  • 异步获取数据,不用刷新页面
  • 数据不包装,节省流量,方便
  • CORS方案带来强大的跨域能力

XMLHttpRequest对象

XMLHttpRequest对象提供了一种更便捷的获取数据的方式,由宿主环境(浏览器)提供。

创建一个完整的Ajax请求有以下步骤:

  1. 创建XHR对象
    通用:
    var xhr = new XMLHttpRequest();
    IE6及IE早期浏览器:
    var xhr = new ActiveXObject('Microsoft.XMLHTTP');

  2. 绑定readystatechange事件
    xhr的readyState属性值用来表示请求的状态:
    - 0 未初始化。尚未调用open()方法。
    - 1 启动。已经调用了open()方法,但尚未调用send()方法。
    - 2 发送。已经调用了send()方法,但尚未接收到响应。
    - 3 接收。已经接收到部分响应数据。
    - 4 完成。已经接收到全部响应数据,而且已经可以在客户端使用了。
    readyState属性值从一个值变为另一个值时触发readystatechange事件,为确保跨浏览器兼容性,要在使用open方法前绑定readystatechange事件:

xhr.onreadystatechange = function() {
  if (xhr.readyState === 4 && xhr.status === 200) {
    // 操作完成且响应成功时执行
  }
};

xhr的status属性值表示HTTP状态码,表示服务端是否成功响应数据
- 200 响应正常
- 301 重定向
- 304 HTTP缓存命中
- 4XX 请求错误
- 5XX 服务器错误

  1. 启动一个请求
    使用open方法启动一个请求:
    xhr.open(method, url, boolean);
  • 参数1(必选):指定请求的方法:'get'、'post'
    - get方法:用于提交简单数据
    - post方法:用于提交复杂数据,需要同时设置RequestHeader:
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  • 参数2(必选):请求的地址
  • 参数3(可选):是否异步:true(默认)、false
  1. 发送请求
    xhr.send(null);
    参数:要作为请求主体发送的数据,可以是字符串或复杂数据类型。如果不需要通过请求主体发送数据,为保障浏览器兼容性,必须传入参数null,此时请求被发送至服务器。

HTTP头部信息

每个HTTP请求和响应都包含相应的头部信息,分别为请求头部和响应头部。XHR对象提供了操作头部信息的方法。如xhr.setRequestHeader()等。

XHR方法

  • xhr.abort();
    舍弃一个请求,在send方法后使用,readyState属性值置为0但不出发readystatechange事件,请求还是会发到服务器
  • xhr.setRequestHeader(key, value);
    设置请求头部信息,同字段多次设置时,值会合并,用逗号隔开,必须在open和send方法中间调用,默认的Accept字段值为"/"。建议使用自定义的字段名,有些浏览器不允许重写默认字段的值。
    参数1:头部字段的名称
    参数2:头部字段的值
    xhr.setRequestHeader('accept', 'text');
  • xhr.getResponseHeader(key);
    获取响应头内容,参数接受响应头字段名,返回字段值,字段名忽略大小写,多个同名字段存在时,多个值以逗号+空格连成一个
    -xhr.getAllResponseHeaders();
    获取所有响应头部信息,返回一个长字符串。如果不包含自定义字段,默认返回多行文本。

其他属性

  • timeout 属性
    设置超时时间,单位为毫秒,超时后出发timeout事件,在IE中必须在open方法后send方法前设置,超时后请求取消
xhr.timeout = 2000;  // 设置超时时间为2秒
xhr.ontimeout = function () {};  // 超时后的回调
  • status 属性
    初始值为0,接收响应头后为标准的HTTP状态码,如果响应头中没有设置状态码,默认为200,XHR出错时,置为0
  • upload 属性
    向服务器上传文件时使用,返回一个XMLHTTPRequestUpload对象,可以通过绑定事件侦听上传过程
  • responseType 属性
    设置响应内容(response)的格式,默认为字符串
    可选值:
    - "" 空字符串,等同于text,表示服务器返回文本数据
    - "arraybuffer" ArrayBuffer对象,表示服务器返回二进制数组
    - "blob" Blob对象,返回二进制对象
    - "document" Document对象,返回文档对象
    - "json" JSON对象
    - "text" 返回字符串
  • response属性
    响应的正文内容,默认为字符串

GET请求和POST请求

GET请求

GET是最常见的请求类型,常用于向服务器查询某些信息,必要时,可以在open()参数中url的末尾加上查询字符串参数。如:
xhr.open('get', 'example.php?name1=value1&name2=value2', true);
格式为:url + '?' + 'key=value&key=value'...
对XHR对象来说,查询字符串必须使用encodeURIComponent()进行编码,可以使用以下函数辅助添加查询字符串参数:

function addURLParam(url, name, value) {
  url += (url.indexOf('?') === -1 ? '?' : '&';
  url += encodeURIComponent(name) + '=' + encodeURIComponent(value);
  return url;
}
POST请求

POST请求通常用来向服务器发送应该被保存的数据。需要有以下步骤:

xhr.open('post', 'postexample.php', true);  // 初始化一个POST请求
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');  // 由于服务器对POST请求和Web表单的请求不会一视同仁,所以此处通过设置请求头来模仿表单提交
xhr.send(data);  // 传入要发送的数据,字符串的形式

XHR 2级中新增了FormData类型,来序列化表单级创建与表单格式相同的数据。

var data = new FormData();  // 新建一个FormData对象
data.append('name', 'Brown');  // 添加数据

或者:

var form = document.getElementById('usere-info');
var data = new FormData(form);

此时不必再设置请求头的Content-Type来模仿表单提交了。

XHR2.0的CORS跨域方案

跨域是指要请求的服务器与当前客户端之间至少存在以下一种情况:不同域名、不同端口、不同协议,由于浏览器的同源策略使得我们不能轻易对非我们站点的域名发起请求。在跨域情况下,Ajax请求会报错。XMLHTTPReques2.0中加入了CORS(跨域源资源共享)跨域方案,只需服务器配合设置响应头:
header('Access-Control-Allow-Origin: *');

简单请求与复杂请求

简单请求需要满足的条件:

  • 请求方法仅限于:HEAD、GET、POST
  • 请求头字段仅限于:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type
  • Content-Type值仅限于:application/x-www-form-urlencoded、multipart/form-data、text/plain

除此之外的均为复杂请求。复杂请求会先发送一次OPTIONS方法的预检请求,如果第一次请求失败,则不会发送第二次请求。

服务端响应头字段设置
  • Access-Control-Allow-Origin:表示允许访问的域名,必须在响应头中设置,一次只能设置一个域名,可使用*表示允许任意域名
  • Access-control-Allow-Credentials:是否允许cookie,值为true时表示允许向服务器发送cookie,客户端需要设置xhr.withCredentials为true,Access-Control-Allow-Origin必须设置为指定域名
  • Access-Control-Expose-Headers:表示允许客户端通过getResponseHeader方法获取的字段。CORS方式下该方法默认只能获取6个基础字段:
    - Cache-Control
    - Content-Language
    - Content-Type
    - Expires
    - Last-Modified
    - Pragma
    获取其他字段的方法:
    客户端在响应成功后:
    xhr.getResponseHeader('Date');
    服务端设置:
    header('Access-Control-Expose-Headers: Date');
  • Access-Control-Allow-Method:表示服务端接受的跨域请求方法。多个方法之间用逗号隔开,必须在预检响应头中设置该字段。
  • Access-Control-Allow-Headers:表示服务端接受的跨域请求的字段。多个字段名用逗号隔开,请求头含Access-Control-Request-Headers时该字段必须设置。
  • Access-Control-Max-Age:表示缓存预检结果。单位为秒,在设置时间内不再发送预检请求。

jQuery中的Ajax方法

全局配置

$.ajaxSetup方法可以设置全局配置,全局配置会作为下次ajax方法的默认参数,可以被ajax方法的配置覆盖,适用于所有基于ajax方法的衍生方法。
示例:

$.ajaxSetup({
  url: './data.json',
  type: 'GET',
  dataType: 'json'
})
function ajax () {
  $.ajax({
    url: './data1.json',  // 重写url
    success: function (data) {
      div.html((JSON.stringify(data, null, 2));
    }
  })
}
全局回调

所有ajax方法默认执行全局回调,可通过配置参数关闭单个ajax方法不执行全局回调,全局回调无法被ajax方法中的配置项覆盖,都会执行,先执行ajax后执行全局。
一共有6个全局回调:

  • ajaxStart:当发送请求且没有其他未完成请求时触发
  • ajaxSend:当请求发送时出发
  • ajaxSuccess:当请求完成时触发
  • ajaxComplete:当请求完成时出发
  • ajaxStop:当请求完成且没有其他未完成请求时出发
  • ajaxError:当请求出错时触发

$.ajax方法:配置参数、返回jqXHR对象,支持Promise方式调用。

$(document).ajaxComplete(function() {  // ajax全局方法必须挂载在document对象上
  console.log('comolete');
})
function ajax() {
  $.get('./data/php', function(data) {
    console.log('ajax dome');
    this.html(JSON.stringify(data, null, 2);  // this指执行上下文
  })
}
$.ajax({
  global: false,  // 表示不会启用全局方法
  success: function() {
    // ...
  }
})

配置参数:

$.ajax({
  url: './data.php',
  type: 'GET',  // 如果是POST需要增加属性data: {}
  dataType: 'json',
  beforeSend: function() {},
  scriptCharset: 'utf-8',
  success: function() {},
  error: function() {},
  complete: function() {},
  xhrFields: {
    width Credentials: true
  },
  timeout: 4000,
  statusCode: {
    304: function() {},
    503: function() {}
  },
  headers: {
    abc: 'xyz',  // 自定义头
  },
  cache: false,  // 不需要缓存
  async: false  // 默认异步true,JSONP无法同步  
})

如果dataType的值设为'jsonp'表示从服务器返回函数,同时需要定义回调jsonpCallback: 'callback',如果不定义,则jQuery自己生成一个函数名。
jqXHR.then(function() {}, function() {});
方法then可以换成其他方法:done(同success)、fail、always、abort
第一个函数表示成功的回调,第二个函数表示失败的回调

jqXHR对象

是浏览器原生XHR对象的一个超集,使用JSONP方式时可以模拟一个XHR对象,是一个deferred object(延迟的对象)
jqXHR的属性:readyState、status、statusText、responseXML、responseText
jqXHR的方法:setRequestHeader、getAllResponseHeaders、getResponseHeader、abort
jqXHR的Promise callbacks:

  • jqXHR.done(function() {}) 成功时的回调
  • jqXHR.fail(function() {}) 失败时的回调
  • jqXHR.always(function() {}) 完成时的回调
  • jqXHR.then(function() {}, function() {}) 传入两个参数表示done和fail时的回调

$.ajax方法的衍生方法

  • $.get(url, 'name=abc', function() {}, 'json');
    参数分别为:请求的地址、发送的数据、成功时的回调、返回数据类型
  • $.post();
    参数同上,同场使用url, data, success三个参数
  • $.getJSON();
    同$.get(url, 'name=abc', function() {}, 'json');省略第四个参数为'json'
  • $.getScript(url, function() {})
    创建一个script标签,src指向url
    第二个参数表示JS加载后的回调
  • jqElement.load();
    向元素中插入数据:
btn.on('click', ajax);
function ajax() {
  div.load('data');
}

转载于:https://www.jianshu.com/p/6562f8bc527c