1. 程式人生 > 實用技巧 >對Promise的理解

對Promise的理解

什麼是Promise;

概念:Promise 代表一個非同步操作;

  1. 建立Promise物件;
// 建立了一個Promise物件;
new Promise()
// 注意:這只是一個【形式上】的非同步操作;因為你不知道里面要幹什麼;是讀檔案還是髮網絡請求呢?
優點:
// 1、可以將非同步操作以同步操作的流程表達出來,避免了層層巢狀的回撥函式。
缺點:
// 1、無法取消 Promise ,一旦新建它就會立即執行,無法中途取消。
// 2、其次,如果不設定回撥函式, Promise 內部丟擲的錯誤,不會反應到外部。
// 3、當處於 pending 狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)

基本用法;

  1. ES6 規定, Promise 物件是一個建構函式,用來生成 Promise 例項;
  2. Promise建構函式接受一個函式作為引數,該函式的兩個引數分別是resolvereject。它們是兩個
    函式,由 JavaScript 引擎提供,不用自己部署。
    1. resolve: 在非同步操作成功時呼叫 ;
    2. reject: 在非同步操作失敗時呼叫,並將非同步操作報出的錯誤,作為引數傳遞出去。
  3. Promise例項生成以後,可以用then方法分別指定resolved狀態和rejected狀態的回撥函式 。
const promise = new Promise(function(resolve, reject) {
  if (/* 非同步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

promise.then(function(value) {
  // 非同步操作成功時的回撥
  }, function(error) {
  // 非同步操作失敗時的回撥
  });
4.	`then`方法;
<script>
// 將一個非同步程式碼包裝到 Promise 中
// 1、定義一個函式
function request(url) {
  // 2、在函式中 return 出一個 Promise 物件
  return new Promise((resolve, reject) => {
    // 3、在 Promise 容器中執行非同步操作
    // 建立請求物件
    var oReq = new XMLHttpRequest();

    // 新增請求回撥函式
    // 請求成功,就會自動執行該回調函式
    oReq.addEventListener("load", function () {

      // 當請求成功了,也就是非同步執行結束了,callback 被呼叫了
      resolve(this.responseText)

      // 只有這裡才能拿到正確的響應結果 responseText 但是在外面取不到;
      // return this.responseText
    });

    oReq.addEventListener("error", function (err) {
      // 失敗 reject
      reject(err)
    });

    // 設定請求方法和請求路徑
    oReq.open("GET", url);

    // 發出請求
    oReq.send();
  })
}

// then 方法之後可以繼續 then
// 原因是 then 方法執行完以後會返回一個新的 Promise 物件
request('http://jsonplaceholder.typicode.com/posts')
  .then(data => {
    // 如果是普通資料,那麼它會把該資料包裝為那個返回的 Promise 的 resolve 結果
    // return new Promise((resolve) => {
    //   resolve('hello')
    // })

    // 因為每個 then 始終返回 promise 物件
    // 所以我才可以在後面繼續 .then
    // 每一個後續的 .then 都是在給上一個 then 中返回的 Promise 物件註冊:resolve、reject

    // 如果你返回的資料就是一個 Promise 物件,那它就不做任何處理了
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve('hello')
      }, 2000)
    })
  })
  .then((data) => {
    return ptimeout(1000)
  })
  .then(() => {
    console.log(3)
  })

function ptimeout(time) {
  return new Promise((resolve) => {
    setTimeout(function () {
      resolve()
    }, time)
  })
}

// Async 函式,簡化了 Promise 的結果獲取而已
</script>

異常處理;

  1.  處理 Promise 中的異常有兩種方式:  
    
    • then方法的第2個引數;
    • 或者 .catch 方法 ;
// 失敗 then 方法的第2個引數來接收處理異常
request('dbsjabdjsabjdsa')
  .then(data => {
    console.log('請求成功', data);
  }, err => {
    console.log('請求失敗', err);
  });
// 使用 .catch 方法接收處理異常
request('dbsjabdjsabjdsa')
  .then(data => {
    console.log('請求成功', data);
  })
  .catch(err => {
    console.log('請求失敗', err);
  });

request('http://jsonplaceholder.typicode.com/posts')
  .then(data => {
    console.log('請求成功', data);
  })
  .catch(err => {
    console.log('請求失敗', err);
  })
// 無論成功或是失敗都會執行
  .finally(() => {
    console.log('無論成功或是失敗都會執行');
  });