## 一、 同步限制
XMLHttpRequest(簡稱xhr)常用的都是異步請求數據,但xhr也可以同步請求數據,但在同步的時候,有些參數必須按要求來限制如下:
xhr.tiemout必須為0
xhr.withCredentials必須為0
xhr.responseType必須為""("text"都不允許)
同步的進候send是阻塞的,此時的xhr.readstate由2變成3,且onreadystatechange事件不為觸發,xhr.upload.onprogress和xhr.onprogress事件也不會觸發。。
## 二 、send
xhr.send(data)的參數類型可以為:
* ArrayBuffer
* Blob
* Document(content-type: text/html;charset=utf-8)
* DOMString(content-type: text/plain;charset=utf-8)
* FormData(content-type: multipart/form-data;boundary=[xxx])
* null
使用圖解:

以FormData為例:
~~~
function sendAjax() {
//構造表單數據
var formData = new FormData();
formData.append('username', 'johndoe');
formData.append('id', 123456);
//創建xhr對象
var xhr = new XMLHttpRequest();
//設置xhr請求的超時時間
xhr.timeout = 3000;
//設置響應返回的數據格式
xhr.responseType = "text";
//創建一個 post 請求,采用異步
xhr.open('POST', '/server', true);
//注冊相關事件回調處理函數
xhr.onload = function(e) {
if(this.status == 200||this.status == 304){
alert(this.responseText);
}
};
xhr.ontimeout = function(e) { ... };
xhr.onerror = function(e) { ... };
xhr.upload.onprogress = function(e) { ... };
//發送數據
xhr.send(formData);
}
~~~
## 三、事件的觸發順序
* 1、觸發xhr.onreadystatechange(這后每次readystate變化時,都會觸發一次)
* 2、觸發xhr.onloadstart
// 上傳階段
* 3、觸發xhr.upload.onloadstart
* 4、觸發xhr.upload.onprogress
* 5、觸發xhr.upload.onload
* 6、觸發xhr.upload.onloadend
// 上傳結束,下載階段
* 7、觸發xhr.onprogress
* 8、觸發xhr.onload
* 9、觸發xhr.onloadend
## 四、示例
**1、post請求**
html
~~~
<input name="username" type="input" />
<input name="password" type="input" />
<button type="button">提交數據</button>
~~~
js
~~~
var $ = document.querySelector.bind(document);
// 點擊提交
$('button').addEventListener('click', handelXhr, false); // useCapture:true(捕獲階段) false(冒泡階段-默認)
// 處理xhr
function handelXhr() {
var xhr = new XMLHttpRequest();
xhr.open('post', 'test.php', true); // true表示異步,false表示同步
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded'); // 模擬form提交,別寫錯了
var data = {
username: $('[name="username"]').value,
password: $('[name="password"]').value
};
xhr.send('username='+data.username+'&password='+data.password);
// 每當 readyState 屬性改變時,就會調用onreadystatechange函數
xhr.onreadystatechange = function() {
if(xhr.readyState==4 && xhr.status==200) {
console.log(JSON.parse(xhr.responseText))
}
}
}
~~~
低版本IE(IE5、IE6)覺得就沒必要記了,像淘寶、京東已經不支持IE7以下的瀏覽器了
~~~
if(window.ActiveXObject) { // IE5、IE6的寫法
new ActiveXObject("Microsoft.XMLHTTP");
}
~~~
php
~~~
<?php
echo json_encode($_POST);
// 也可以使用file_get_contents('php://input', 'r')獲取整個send
?>
~~~
結果

下面看下readyState的5種狀態
| 狀態碼 | 狀態描述 |
| --- | --- |
| 0 | 請求未初始化 |
| 1 | 服務器連接已建立 |
| 2 | 請求已接收 |
| 3 | 請求處理中 |
| 4 | 請求已完成,且響應已就緒 |
在看下status狀態
| 狀態碼 | 狀態描述 |
| --- | --- |
| 200 | OK |
| 404 | 未找到頁面 |
事件
| 事件 | 描述 |
| --- | --- |
| onabort | 當請求中止時觸發 |
| onload | 當請求成功時觸發 |
| onloadend | 在請求成功或者失敗時觸發;load、abort、error、timeout事件發生之后 |
| onloadstart | 當請求開始時觸發 |
| onreadystatechange | 當readyStateChange屬性改變時觸發 |
| ontimeout | 當timeout屬性指定的時間已經過去但響應依舊沒有完成時觸發 |
| onerror | 當請求因錯誤失敗時觸發。注意404等狀態碼不是error,因為此時響應仍然是成功完成的 |
| onprogress | 當響應主體正在下載重復觸發(約每隔50ms一次) |
**2、get請求**
js
~~~
function handelXhr() {
var data = {
username: $('[name="username"]').value,
password: $('[name="password"]').value
};
var xhr = new XMLHttpRequest();
xhr.open('get', 'test.php?username='+data.username+'&password='+data.password, true); // true表示異步,false表示同步
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded'); // 模擬form提交,別寫錯了
xhr.send(null);
// 每當 readyState 屬性改變時,就會調用onreadystatechange函數
xhr.onreadystatechange = function() {
if(xhr.readyState==4 && xhr.status==200) {
console.log(JSON.parse(xhr.responseText))
}
}
}
~~~
php
~~~
<?php
echo json_encode($_GET);
~~~
get和post的區別就是傳遞參數的方式不一樣
**3、使用loading**
先看下XMLHttprRequest對象都有哪些屬性和方法

從中可以找到onprogress方法和onload方法
~~~
function handelXhr() {
var data = {
username: $('[name="username"]').value,
password: $('[name="password"]').value
};
var xhr = new XMLHttpRequest();
xhr.open('get', 'test.php?username='+data.username+'&password='+data.password, true); // true表示異步,false表示同步
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded'); // 模擬form提交,別寫錯了
xhr.send(null);
// 加載中
var p = document.createElement('p');
xhr.onprogress = function() {
p.innerHTML = '加載中...';
$('body').appendChild(p);
}
// 每當 readyState 屬性改變時,就會調用onreadystatechange函數
xhr.onreadystatechange = function() {
if(xhr.readyState==4 && xhr.status==200) {
console.log(JSON.parse(xhr.responseText));
// $('body p').parentNode.removeChild(p); 也可以在這里刪除
}
}
// 加載完成
xhr.onload = function() {
$('body p').parentNode.removeChild(p);
}
}
~~~
**4、超時設置**
~~~
xhr.timeout = 10000; // 10秒
xhr.ontimeout = function() {
console.log('請求超時');
}
~~~
**5、取消請求**
~~~
xhr.abort();
~~~
**6、withCredentials**
默認情況下,跨源請求不提供憑據(cookie、HTTP認證及客戶端SSL證明等)。通過將withCredentials屬性設置為true,可以指定某個請求應該發送憑據。如果服務器接收帶憑據的請求,會用下面的HTTP頭部來響應。
~~~
Access-Control-Allow-Credentials: true
~~~
如果發送的是帶憑據的請求,但服務器的相應中沒有包含這個頭部,那么瀏覽器就不會把相應交給JavaScript(于是,responseText中將是空字符串,status的值為0,而且會調用onerror()事件處理程序)。另外,服務器還可以在Preflight響應中發送這個HTTP頭部,表示允許源發送帶憑據的請求。
支持withCredentials屬性的瀏覽器有Firefox 3.5+、Safari 4+和Chrome。IE10及更早版本都不支持。
**7、responseType**
| 類型 | 描述 |
| --- | --- |
| "" | DOMString (默認值) |
| arraybuffer | ArrayBuffer |
| blob | Blob |
| document | document |
| json | JSON |
| text | DOMString |
~~~
// responseType=json示例
function handelXhr() {
var data = {
username: $('[name="username"]').value,
password: $('[name="password"]').value
};
var xhr = new XMLHttpRequest();
xhr.open('get', 'test.php?username='+data.username+'&password='+data.password, true);
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
xhr.responseType = 'json';
xhr.send(null);
xhr.onreadystatechange = function() {
if(xhr.readyState==4 && xhr.status==200) {
console.log(xhr.response);
}
}
}
~~~
簡單封裝
~~~
function ajax(options) {
var defaults = {
type: 'get',
url: '',
isAsync: true,
data: null,
success: function() {},
error: function() {},
complete: function() {}
};
var conf = Object.assign({}, defaults, options);
var xhr = new window.XMLHttpRequest();
xhr.open(conf.type, conf.url, conf.isAsync);
xhr.send(conf.data);
// 狀態改變
xhr.onreadystatechange = function() {
if(this.readyState!=4 || this.status!=200) {
// 添加loading
} else {
// 刪除loading
}
}
// 請求成功
xhr.onload = function() {
if(this.readyState==4 && this.status==200) {
conf.success.call(null, this.response, this);
}
};
// 失敗
xhr.onerror = function() {
conf.error.call(this);
};
// 加載結束,不管成功還是失敗
xhr.onloadend = function() {
conf.complete.call(this);
};
}
// 調用
ajax({
url: 'demo.php',
success: function(data) {
console.log(JSON.parse(data));
},
error: function() {
alert('失敗');
},
complete: function() {
alert('完成');
}
});
~~~
## 六、jquery相關封裝
~~~
var data = {
username: $('[name="username"]').value,
password: $('[name="password"]').value
};
$.ajax({
type: 'get',
url: 'test.php',
data: data,
beforeSend: function() { // 發送前
// 顯示loading層
},
success: function(res) { // 成功
console.log(res);
// 隱藏loading層
},
error: function() { // 報錯
console.log('請求出錯');
},
complete: function() { // 成功/報錯
console.log('完成~');
}
});
~~~
除此還有
~~~
$.post(url , [data], [callback], [type]);
~~~
~~~
$.get(url , [data], [callback], [type]);
~~~
這里的type可以為:xml, html, script, json, text, _default,是jquery封裝好的responseType
## 七、跨域
**1、后臺添加如下代碼**
~~~
header( 'Access-Control-Allow-Origin:*' );
~~~
**2、使用jsonp**
原理在地址中添加url?callback=handel,然后頁面調用handel函數,如:
~~~
handel({"username":"1","password":"2"})
~~~
下面是請求截取的字段也可以看出
~~~
// Request URL:http://localhost/test/test.php?call=handel
// Query String Parameter
// call:handel
~~~
示例:
js
~~~
function callback(res) {
console.log(res);
}
$.ajax({
type: 'get',
url: 'demo.php',
dataType: 'jsonp'
});
~~~
php
~~~
$a = array('name'=>'tom','age'=>23);
echo 'callback('.json_encode($a).')';
~~~
自定義請求參數名和回調函數名
js
~~~
function handel(res) {
console.log(res);
}
$('button').click(function() {
$.ajax({
type:'post',
url: 'test.php',
data: {username: 'tom', password: '123456'},
dataType: 'jsonp',
jsonp: 'call',
jsonpCallback: 'handel'
});
});
~~~
php
~~~
echo $_GET['call'].'('.json_encode($_POST).')';
~~~
- 事件
- mouse縮放與拖動
- drag拖動
- 事件兼容
- animation/transition
- canvas
- 改變圖片顏色
- html轉圖片
- 視頻操作
- 圖片縮放、水印、放大鏡
- 虛線
- 圓環進度條
- 形狀事件
- 圓角矩形
- 繪制注意
- arcTo與貝塞爾
- 橢圓及橢圓進度
- 五角星進度
- 常用圖形
- 計算顯示文本寬度
- 算法
- 幾何算法
- 地圖應用相關
- 運行符
- web安全
- 新窗口打開
- xss
- 分享交流
- php環境搭建及xhr交互
- node環境搭建及xhr交互
- node之socketio
- svg之入門介紹
- svg動畫
- vue之搜索聯想
- vue之登錄和echarts
- vue之組件交互與slot
- vue之loading
- vue之上傳進度
- webpack及cli
- 開發技巧
- 常用
- 移動端
- 錯誤處理
- 預加載
- 代理判斷
- 數組擴展
- 對象擴展
- 字符串擴展
- 語音播報
- 收集
- 文章/日記
- 框架/庫/插件
- 工具
- 學習網站
- 專業術語
- 正則
- 常用驗證
- 方法基礎
- es6擴展
- 深入實踐
- 快捷使用
- html
- css
- http協議
- http
- https
- socket
- 地圖/圖表
- mapbox
- echarts
- arcgis
- MapView及事件
- 添加WMS/WMTS層
- 增刪點線面
- 入門使用
- popup彈層
- 大數據處理
- 批量點
- 批量線
- 在線繪制
- GraphicLayer顯示/隱藏
- 動態改變位置
- 去除版權信息
- 添加控件
- Symbol
- 自定義path標記
- 圖片標記
- 文本標記
- 旋轉
- UI
- 自定義
- 3D地圖
- 創建實例
- basemap
- 底圖切換
- 自定義底圖
- 中心和范圍
- pupup彈層更新
- 坐標轉換
- 方向線
- leaflet
- amap
- 框架/類庫/腳手架
- vue
- 常見問題
- 組件框架
- vue-router
- 命名視圖
- url參數映射到prop
- sublime支持
- 隨手記
- 常用功能
- threejs
- 常用效果
- 其他特效
- requirejs
- 簡單使用
- jquery
- 方法擴展
- 使用筆記
- 組件擴展
- react
- 黨見問題
- 學習筆記
- 學習筆記-進階
- react-redux
- react-router
- redux
- 其他模塊說明
- 組件框架
- sublime支持
- gulp
- 安裝使用
- js壓縮
- css壓縮
- 組合使用
- copy文件
- 項目使用
- protobuf
- 入門
- layui
- 登錄驗證
- laydate
- 安裝工具
- yarn
- reactNative
- 入門介紹
- vueNative
- 入門介紹
- 版本控制
- git常用
- git擴展
- git問題
- git其他
- git擴展2
- 編輯器
- vscode
- atom
- webstorm
- 插件
- clipboard
- 奇淫巧技
- js
- 個性打印
- css
- 濾鏡效果
- 文本省略
- 當前色
- 新特性
- 花樣邊框效果
- 波紋效果
- 個性placeholder
- 偽元素內容
- 容器居中
- 知識點
- js
- 遞歸
- 沙箱
- 內存泄漏
- es6語法
- 變量介紹
- FileRead
- ajax
- web存儲
- css
- rem布局