Promise
簡單來說,Promise主要就是爲了解決異步回調的問題。用Promise來處理異步回調使得代碼層次清晰,便於理解,且更加容易維護。
語法
new Promise( /* executor */ function(resolve, reject) { ... } );
參數:一個有兩個參數爲函數的函數,這個函數會立即執行。你可以在這個方法體中作異步操作,異步操作完成後,應調用resolve函數,Promise有三種狀態:pending狀態( 初始狀態);fulfilled狀態(操作完成時的狀態);rejected狀態(操作失敗時的狀態)【注意:Promise結束時會再次處於pending狀態】 。fulfilled狀態與resolve對應,rejected狀態與reject對應,也就是異步操作失敗後,應調用reject函數。
方法
p.then(onFulfilled[, onRejected]);
p.then(function(value) {
// fulfillment
}, function(reason) {
// rejection
});
參數:onFulfilled是一個函數,Promise完成時調用;onRejected是一個函數,Promise被拒絕即失敗時調用。
p.catch(onRejected);
p.catch(function(reason) {
// rejection
});
參數:catch只有一個參數,也是個函數,Promise失敗時調用。
詳情請查閱:Promise MDN火狐官方開發文檔
場景
我們需要使用XMLHttpRequest異步的方式向服務器發送請求來獲取token值,然後,使用XMLHttpRequest異步地將獲取的token和必要的數據發送到服務器。
這是一個異步嵌套異步的結構。我們將通過Promise對象去實現異步控制。
代碼
let saveToServer = function(sJson) {
//獲取token
let oPromise = new Promise(function(success, error){
let oXhr = new XMLHttpRequest();
let sUrl = "/getCsrf.html";
oXhr.open("get", sUrl, true);
oXhr.send(null);
oXhr.onreadystatechange = function() {
if(oXhr.readyState == 4) {
if(oXhr.status == 200) {
//oXhr.responseText:"<input type="text" name="${_csrf.parameterName}" value="${_csrf.token}">"
let sInput = oXhr.responseText;
let eInput = {};
//將sInput轉爲eInput
let eDiv = document.createElement("div");
eDiv.innerHTML = sInput;
if(eDiv.childNodes.length > 0){
eInput = eDiv.childNodes[0];
let sToken = eInput.value;
let sName = eInput.getAttribute("name");
success({sName: sName, sValue: sToken});
}else{
error(oXhr.responseText);
}
}
else
Console.error("saveToServer(): Fail to get _token from server: " + oXhr.status);
}
}
});
//token獲取成功,發送打標詞組
oPromise.then(function(jToken){
let oXhr = new XMLHttpRequest();
let sUrl = "saveAnnotate.html?"+ jToken.sName + "=" + jToken.sValue;
oXhr.open("post", sUrl, true);
oXhr.send(sJson);
oXhr.onreadystatechange = function() {
if(oXhr.readyState == 4) {
if(oXhr.status == 200) {
let sMsg = oXhr.responseText.trim();
Console.debug("saveToServer(): response is " + sMsg);
if (sMsg.indexOf("success") >= 0) {
…… ……
}
else {
alert("失敗!");
}
}
else
Console.error("saveToServer(): Fail to communicate with server: " + oXhr.status);
}
}
});
//token獲取失敗
oPromise.catch(function(sMsg){
Console.error("saveToServer(): token format error: " + sMsg);
});
}