on 2015-01-10

AJAX - XMLHttpRequest Introduction

Intro

說到 AJAX 行為就不行不提到 XMLHttpRequest object

不知道現在的前端工程師還有人認識這個東西嗎?

當前 library 眾多(YIU, jQuery, AngularJS, Backbone.js…)

可能用過

  • Y.jsonp(url, callback);
  • $.ajax();
  • $http();
  • ……

這些處理 AJAX 行為的 method

這些 library 在處理 AJAX 行為時其實都是 base on XMLHttpRequest

所以就來簡單說明一下這玩意, 了解這東西其實有助於處理 AJAX 行為

因為這算是在前端開發上會較接觸到網路 http Protocol 的東西, 也跟後端有較緊密的關係

History

其實在早期 XMLHttpRequest 尚未定案下來時也有許多名稱

var httpRequest;
if (window.XMLHttpRequest) {
    // IE7,Mozila,Safari...
    httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) {
    // IE5,IE6
    // 找出最新版MSXML剖析器
    var msxmls = ["MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp","Mircosoft.XMLHttp"];
    for (i = 0; i < msxmls.length; i++) {
        try {
            // 建立XMLHttpRequest物件
            httpRequest = new ActiveXObject(msxmls[i]);
            break;
        } catch (e) {
            // do something
        }
    }
}

相信看過這段 code 的人大概都會會心一笑

在早期確實還是要去判斷該物件是否存在來兼容各 browser

在處理 AJAX 上也不像現在都包好好, 都是自己處理許多行為, 但這樣也會較了解真實運作的原理

var xhr = new XMLHttpRequest();

xhr.open('GET', 'example.html', true);
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        document.getElementById('myDiv').innerHTML = xhr.responseText;
    }
};
xhr.send();

上列為早期最簡單的一個 AJAX 行為

從上面的 code 就可以看出要用 GET 來作取資料的動作, 所以就必須了解 http 原來有 GET, POST, DELETE, PUT 等等的 method

xhr.status 可以了解到原來 http Protocol 有定義許多 status code 來表示 request 最後 response 的狀態

甚至許多人大概很少處理 timeout, abort, setRequestHeader

其實都有定義, 而要有一個嚴謹的 AJAX 行為其實並不是單純的使用 library 處理 success 或 error, 其實有很多情況要處理

必須要很了解 AJAX 的流程與許多可能發生的例外狀況

例如 padding 時間過久是否要重發還是取消, error 發生時依據 http status code 適當的 feedback 到畫面上等等都是在處理 AJAX 行為要注意的事

Data Transfer

在使用 library 時大家都知道要帶參數到後端大部份只要把參數帶入用 json 格式包起來的 object 中就可以了, 但卻不知道其實 library 都幫忙實作好多東西了

其實有兩種方式可以帶參數到後端

  • FormData
  • application/x-www-form-urlencoded

但這東西說穿了就是像是利用 form 的方式來傳送資料

FormData

// FormData
var formData = new FormData();
formData.append('str', 'string');
formData.append('num', 123);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'test.php');
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        document.getElementById('myDiv').innerHTML = xhr.responseText;
    }
};
xhr.send(formData);

PHP 部分

$str = $_POST['str'];
$num = $_POST['num'];

application/x-www-form-urlencoded

// application/x-www-form-urlencoded
var obj = {
        'user': 'ted',
        'password': '123456'
    },
    jsonData;
jsonData = JSON.stringify(obj);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'test.php', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        document.getElementById('myDiv').innerHTML = xhr.responseText;
    }
};
xhr.send('json=' + jsonData);

PHP 部分

$request_json = json_decode($_POST['json'], true);

較常用的方式會是建立 FormData 的方式來處理

但由於 IE 10 以上才支持 FormData

所以在未支援的情況下建議使用 application/x-www-form-urlencoded 的方式

關於一些 AJAX 的進階應用與 request/response 行為以後會有文章說明