1. 程式人生 > 其它 >ES6 Promise物件--將非同步程式碼像同步程式碼那些書寫

ES6 Promise物件--將非同步程式碼像同步程式碼那些書寫

ES6 Promise物件--將非同步程式碼像同步程式碼那些書寫

部落格說明

文章所涉及的資料來自網際網路整理和個人總結,意在於個人學習和經驗彙總,如有什麼地方侵權,請聯絡本人刪除,謝謝!

簡介

從語法上說,Promise 是一個物件,從它可以獲取非同步操作的訊息。Promise 提供統一的 API,各種非同步操作都可以用同樣的方法進行處理。通俗來說,Promise是一個容器,裡面儲存著非同步操作的結果。

特點

物件的狀態不受外界影響

Promise物件有三種狀態:pending(進行中)、fulfilled(已成功)和rejected(已失敗)。

只有非同步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。

一旦狀態改變,就不會再變,任何時候都可以得到這個結果

Promise物件的狀態改變,只有兩種可能:從pending變為fulfilled和從pending變為rejected。只要這兩種情況發生,狀態就凝固了,不會再變了,並且會一直保持這個結果,這時就稱為 resolved(已定型)。

優點與缺點

優點

1、Promise物件可以將非同步操作以同步操作的流程表達出來,用同步的方式寫非同步的程式碼,避免了層層巢狀的回撥函式。

2、Promise物件提供統一的介面,使得控制非同步操作更加容易。

缺點

1、無法取消Promise,一旦新建它就會立即執行,無法中途取消。

2、如果不設定回撥函式,Promise

內部丟擲的錯誤,不會反應到外部。

3、第三,當處於pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。

案例

Promise例項

Promise建構函式接受一個函式作為引數,該函式的兩個引數分別是resolvereject。注意這兩個是兩個函式。

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 非同步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

resolve函式的作用是,將Promise

物件的狀態從“未完成”變為“成功”(即從 pending 變為 resolved),在非同步操作成功時呼叫,並將非同步操作的結果,作為引數傳遞出去;

reject函式的作用是,將Promise物件的狀態從“未完成”變為“失敗”(即從 pending 變為 rejected),在非同步操作失敗時呼叫,並將非同步操作報出的錯誤,作為引數傳遞出去。

Promise執行順序

Promise 新建後就會立即執行。

let promise = new Promise(function(resolve, reject) {
  console.log('11');
  resolve();
});

promise.then(function() {
  console.log('22');
});

console.log('33');

// 11
// 33
// 22

Promise 新建後立即執行,所以首先輸出的是11then方法指定的回撥函式屬於非同步函式,在當前指令碼所有同步任務執行完才會執行,所以輸出3322最後輸出。

非同步載入圖片案例

使用Promise包裝了一個圖片載入的非同步操作。如果載入成功,就呼叫resolve方法,否則就呼叫reject方法。

function loadImageAsync(url) {
  return new Promise(function(resolve, reject) {
    const image = new Image();

    image.onload = function() {
      resolve(image);
    };

    image.onerror = function() {
      reject(new Error('Could not load image at ' + url));
    };

    image.src = url;
  });
}
Promise物件實現的 Ajax

getTest函式中對 XMLHttpRequest 物件進行了封裝,傳送一個 HTTP 請求,得到一個Promise物件。

const getTest = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

  });

  return promise;
};


// 呼叫案例
getTest("/test.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error(error);
});

Promise錯誤處理

如果 Promise 狀態已經變成resolved,再丟擲錯誤是無效的。因為 Promise 的狀態一旦改變,就永久保持該狀態,不會再變了。

Promise 物件的錯誤具有冒泡性質,會一直向後傳遞,直到被捕獲為止。也就是說,錯誤總是會被下一個catch語句捕獲。

const promise = new Promise(function(resolve, reject) {
  resolve('ok');
  throw new Error('test');
});
promise
  .then(function(value) { console.log(value) })
  .catch(function(error) { console.log(error) });
// ok

感謝

萬能的網路

阮一峰的es6語法教程

以及勤勞的自己,個人部落格GitHub