JavaScript異步控制 ---- Promise的一個簡單使用場景

Promise

簡單來說,Promise主要就是爲了解決異步回調的問題。用Promise來處理異步回調使得代碼層次清晰,便於理解,且更加容易維護。

語法

new Promise( /* executor */ function(resolve, reject) { ... } );

參數:一個有兩個參數爲函數的函數,這個函數會立即執行。你可以在這個方法體中作異步操作,異步操作完成後,應調用resolve函數,Promise有三種狀態:pending狀態( 初始狀態);fulfilled狀態(操作完成時的狀態);rejected狀態(操作失敗時的狀態)【注意:Promise結束時會再次處於pending狀態】 。fulfilled狀態與resolve對應,rejected狀態與reject對應,也就是異步操作失敗後,應調用reject函數。
Promise狀態圖

方法

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);
    });
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章