Ajax是Asynchronous JavaScript+XML(异步JavaScript和XML)的缩写。javascript
该名称诞生于XML仍是数据传输首选格式的时期,如今这种状况已经不复存在。尽管X在Ajax中表明XML, 但因为JSON的许多优点,好比更加轻量以及做为Javascript的一部分,目前 JSON 的使用比XML更加广泛。JSON和XML都被用于在Ajax模型中打包信息。php
Ajax技术的核心是 XMLHttpRequest对象 (简称XHR)。XHR为向服务器发送请求和解析服务器响应提供了流畅的接口。可以以异步方式从服务器取得更多信息,意味着用户单击后,不用刷新页面也能得到新数据。便可以使用XHR对象取得新数据,而后经过DOM将新数据插入到页面中。html
Ajax的好处:java
XMLHttpRequest对象的特色:jquery
只要xhr.readyState的值改变一次,就会触发一次readystatechange事件。因此能够利用该事件来检测readyState发生变化后的值。es6
readystatechange事件处理程序只能经过xhr.onreadystatechange(DOM0级法法)来绑定才能确保跨浏览器的兼容性,由于并不是全部浏览器都支持DOM2级方法ajax
请求/响应过程的当前活动阶段。该属性可能的值为:json
响应的HTTP状态码。一般是将 200<= 状态码 <300 或 status为304做为响应成功的标志。api
Tips: 304表示请求的资源并无被修改,能够直接使用浏览器缓存中的版本,因此也意味着响应有效。跨域
HTTP状态的说明文字。
做为响应主体被返回的文本。
初始化一个请求。
参数:
method:请求所使用的HTTP方法; 例如 "GET", "POST", "PUT", "DELETE"等
url:该请求要访问的url。能够是绝对地址,也能够是相对于执行代码的当前页面的相对地址。
async:布尔值,是否异步发送请求,默认为true
user(可选):用户名,为受权使用;默认为空string.
password(可选):密码,可选参数,为受权使用;默认为空string.
注意: 调用该方法并不会真正发送请求,只是启动一个请求以备发送。
发送请求. 若是该请求是异步模式(默认),该方法会马上返回. 相反,若是请求是同步模式,则直到请求的响应彻底接受之后,该方法才会返回.
参数:
若是请求已经被发送,则马上终止请求。
调用这个方法后,XHR对象会中止触发事件readystatechange,也再也不容许访问任何与响应有关的对象属性。
默认会发送的请求头有:
该方法会设置自定义的请求头部信息。
参数:
获取相应响应头字段的信息。
参数:
取得包含全部响应头部信息的长字符串。
XMLHttpRequest level2级接口。
FormData为序列化表单以及建立与表单格式相同的数据(用于XHR传输)提供了便利。
能够这样向FormData构造函数传入表单元素来填入键值对:
var data = new FormData(document.forms[0]);
也可使用append方法添加任意多个键值对:
var data = new FormData(); data.append('name', 'Bonnie');
FormData对应数据的"Content-Type"为"multipart/form-data",这也是该表头的默认值,故使用FormData能够没必要明确为Content-Type设置值,这是它的方便之处。
<div> <button id="btn">Apples</button> </div> <div id="target"> </div> <script> var button=document.getElementById("btn"); button.onclick=handleButtonPress; function handleButtonPress(e) { var xhr=new XMLHttpRequest();//建立XMLHttpRequest对象 xhr.onreadystatechange=function(){ if (xhr.readyState==4) {//xhr.readyState:该属性表示请求/响应过程的当前活动阶段,4为完成,其值每变化一次都会触发一次readystatechange事件 if ((xhr.status>=200&&xhr.status<300)||xhr.status==304) {//xhr.status:响应的状态 //304状态码:客户端已经执行了GET,但文件未发生变化,即服务器若是发现资源没有改变过,那么就会返回304,告诉浏览器,我没变过,你去读缓存吧,因而浏览器也不用从服务器拉数据了 document.getElementById("target").innerHTML=xhr.responseText;//xhr.responseText:做为响应主体被返回的文本 } else{ document.getElementById("target").innerHTML="Request was unsuccessful: "+xhr.status; } } } xhr.open("GET","example.html",true);//要发送的类型、请求的URL和是否异步发送 xhr.send(null);//发送做为请求主体要发送的数据 } </script>
Tips:GET请求常常会发生查询字符串格式有问题的错误。解决方法:查询字符串中每一个参数的名称和值都必须使用encodeURIComponent()进行编码。如下是一个向URL末尾添加查询字符串参数的方法:
function addUrlParam(url, name, value) { url += ( url.indexOf('?') === -1 ? '?' : '&'); url += encodeURIComponent(name) + '=' + encodeURIComponent(value); }
<form id="fruitform" method="post" action="localhost:3000/form"> <p>Bsnanas:</p> <p><input name="bananas" value="2"/></p> <p>Apples:</p> <p><input name="apples" value="5"/></p> <p>Cherries:</p> <p><input name="cherries" value="20"/></p> <p>Total:</p> <div id="results">0 items</div> <button id="submit" type="submit">Submit Form</button> </form> <script> document.getElementById("submit").onclick=handleButtonPress; function handleButtonPress(e) { e.preventDefault();//取消按钮提交表单的默认行为 var form=document.getElementById("fruitform"); var formData=new Object(); var inputElements=document.getElementsByTagName("input"); for (var i=0;i<inputElements.length;i++) { formData[inputElements[i].name]=inputElements[i].value; }//将表单提交的数据转换为object类型 var xhr=new XMLHttpRequest();//建立XMLHttpRequest()对象 xhr.onreadystatechange= function(){//为xhr.onreadystatechange设置事件监听函数,readystatechange改变的时候触发 if (xhr.readyState==4) { if (xhr.status>=200&&xhr.status<300||xhr.status==304) { var data=JSON.parse(xhr.responseText);//把JSON数据解析为对象 document.getElementById("results").innerHTML="You ordered "+data.total+" items"; } } } xhr.open("post",form.action,true);//xhr.open()设置post方法,发送到的URL,是否异步 xhr.setRequestHeader("Content-Type","application/json");//设置请求的首部字段Content-Type为application/json,告诉服务器在发送json数据 xhr.send(JSON.stringify(formData));//浏览器向服务器发送数据前,要把数据从Object转换为JSON字符串 } </script>
<script> document.getElementById("submit").onclick=handleButtonPress; function handleButtonPress(e) { e.preventDefault();//取消按钮提交表单的默认行为 var form=document.getElementById("fruitform"); var formData=""; var inputElements=document.getElementsByTagName("input"); for (var i=0;i<inputElements.length;i++) { formData+=inputElements[i].name+"="+inputElements[i].value+"&"; }//将表单提交的数据转换为编码表单数据的默认方式(application/x-www-form-urlencoded编码)。 var xhr=new XMLHttpRequest();//建立XMLHttpRequest()对象 xhr.onreadystatechange=function() {//为xhr.onreadystatechange设置事件监听函数,readystatechange改变的时候触发 if(xhr.readyState == 4) { if(xhr.status >= 200 && xhr.status < 300 || xhr.status==304) { document.getElementById("results").innerHTML = xhr.responseText; } } } xhr.open("post",form.action,true);//xhr.open()设置post方法,发送到的URL,是否异步 xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");//设置请求的首部字段Content-Type为application/json,告诉服务器在发送json数据 xhr.send(formData);//浏览器向服务器发送数据前,要把数据从Object转换为JSON字符串 } </script>
var data = new FormData(document.forms[0]);//能够这样向FormData构造函数传入表单元素来填入键值对 /*也可使用append方法添加任意多个键值对。 var data = new FormData(); data.append('name', 'Bonnie'); */ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) { console.log(xhr.responseText) } } } xhr.open('POST', 'post.php', true); xhr.send(data);
http://api.jquery.com/jQuery.ajax/
执行Ajax请求。
$.ajax({ method: 'POST', url:'example.php', data: { name: 'Bonnie', age: 26 }, dataType:'json' }).done(function(msg){ console.log(msg); })
$.ajax('example.php') .done(function(){ alert('success'); }) .fail(function() { alert('error'); }) .always(function() { alert('complete') })
请求的地址。
这里列出一些重点配置属性:
default 'application/x-www-form-urlencoded; charset=UTF-8')
告诉服务器发送的数据类型。
default: false for same-domain requests, true for cross-domain requests)
是否跨域
Type: object or string or array)
要发送到服务器的数据。
default: Intelligent Guess (xml, json, script, or html)
Type: String
The type of data that you're expecting back from the server. If none is specified, jQuery will try to infer it based on the MIME type of the response (an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string)
dataTye字段指明你指望从服务器返回的数据类型,若是没有指定值,那么jQuery将尝试根据response的MIME类型来推断该数据类型(XML MIME类型将产生XML, 1.4版本的JSON将产生JavaScript对象,1.4版本的script将产生script,其余类型将返回字符串)
实践中遇到的问题:
若是服务端php不指定header类型,那么response数据默认分配成text/html;此时,若客户端ajax不指定dataType,则在done里接收的data为string类型,这样还须要JSON.parse对其进行处理
若是服务端php指定header类型为application/json,那么response的数据类型就为JSON字符串;此时,若客户端ajax不指定dataType,则在done里接收的data就为JavaScript object类型,这样就不须要经过JSON.parse对其进行处理。
请求成功的回调函数
请求错误的回调函数
请求成功和失败都会执行的回调函数。
Fetch API提供了一个获取资源的借口(包括跨域)。它提供了许多与XMLHttpRequest相同的功能,但被设计成更具可扩展性和高效性。
Fetch 的核心在于对 HTTP 接口的抽象,包括 Request,Response,Headers,Body,以及用于初始化异步请求的 global fetch。
[Service Workers]s(https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_APIs) 是大量使用Fetch的API的一个示例。
它返回一个 promise,这个promise会在请求响应后被resolve,并传回Response对象。
当遇到网络错误时,fetch()返回的promise会被reject,并传回TypeError。
成功的fetch()检查不只要包括promise被resolve,还要包括Response.ok属性为true.
fetch(urlStr) .then( res => res.json()) //res是一个response对象,并非咱们指望的json结果。为了获取JSON内容,咱们须要使用 json()方法。res.json()方法返回的也是一个promise对象,因此须要再一次地使用then() .then( myJson => { console.log(myJson) })
fetch(urlStr, { method: 'POST', // *GET, POST, PUT, DELETE, etc. body: JSON.stringify(data),//须要和请求头字段Content-Type保持一致。这里是发送json字符串 headers: { 'content-type': 'application/json' }, /* or: headers: new Headers({ 'Content-Type': 'application/json' }) */ }) .then(res => res.json()) .catch(error => console.error('Error:', error)) .then(data => console.log(data))
加上对请求是否成功的验证:
fetch(urlStr, { method: 'POST', // *GET, POST, PUT, DELETE, etc. body: JSON.stringify(data),//须要和请求头字段Content-Type保持一致。这里是发送json字符串 headers: { 'content-type': 'application/json' }, }) .then(res => { if(res.ok) { return res.json(); } throw new Error('Network response was not ok.'); }) .catch(error => console.error('Error:', error.message)) .then(data => console.log(data))
Fetch API中的Body类表明Response/Request的body,容许你声明其内容类型是什么以及应该如何处理。
Body类由Response类和Request类实现,这为对象response和request提供了一个相关联的body(字节流)
只读:包含一个指示body是否被读取过的 Boolean 值。
使用一个 JSON 对象来读取 Response流中的数据,并将bodyUsed状态改成已使用。
返回:一个promise, resolve的结果是Json 对象 而非字符串(即通过JSON.parse()解析过的JSON字符串)
使用一个 FormData 对象来读取 Response流中的数据,并将bodyUsed状态改成已使用。
返回: 一个 Promise,resolve的结果是FormData 对象。
使用一个USVString (文本) 对象来读取 Response流中的数据,并将bodyUsed状态改成已使用。
返回:一个包含USVString对象 (text)的Promise,resolve的结果的编码为UTF-8。
注意: 其与Body.json()方法的区别:一样是请求json字符串文本:
使用一个buffer数组来读取 Response流中的数据,并将bodyUsed状态改成已使用。
返回:A promise that resolves with an ArrayBuffer.
使用一个Blob对象来读取Response流中的数据,并将bodyUsed状态改成已使用。
返回:A promise that resolves with a Blob.
Headers 接口容许您对HTTP请求和响应头执行各类操做。 这些操做包括检索,设置,添加和删除.
let myHeader = new Headers()
给现有的header添加一个值, 或者添加一个未存在的header并赋值.
从Headers对象中删除指定header
从Headers对象中返回指定header的第一个值.
{ body: JSON.stringify(data), // must match 'Content-Type' header cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached credentials: 'same-origin', // include, same-origin, *omit headers: { 'user-agent': 'Mozilla/4.0 MDN Example', 'content-type': 'application/json' }, method: 'POST', // *GET, POST, PUT, DELETE, etc. mode: 'cors', // no-cors, cors, *same-origin redirect: 'follow', // manual, *follow, error referrer: 'no-referrer', // *client, no-referrer }
请求的方法
请求头信息
请求的模式:
请求的凭据,如 omit、same-origin 或者 include。为了在当前域名内自动发送 cookie , 必须提供这个选项。
可用的重定向模式: follow (自动重定向), error (若是产生重定向将自动终止而且抛出一个错误), 或者 manual (手动处理重定向).
能够是 no-referrer、client或一个 URL
《JavaScript高级程序设计》21.1,21.2
https://developer.mozilla.org/zh-CN/docs/Web/Guide/AJAX
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
http://api.jquery.com/jQuery.ajax/
https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API#
https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
https://developer.mozilla.org/zh-CN/docs/Web/API/Body
https://developer.mozilla.org/zh-CN/docs/Web/API/Request
https://developer.mozilla.org/zh-CN/docs/Web/API/Response
https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/fetch