Promise--感性認知

mybydhn醬發表於2018-09-10

Promise--感性認知

1.什麼是Promise

Promise是非同步程式設計的一種解決方案,比回撥更合理更強大。從語法上來說,Promise是一個物件,從它可以獲取非同步操作的資訊。 Promise物件有以下兩個特點:

  1. 物件的狀態不受外界影響。Promise物件代表一個非同步操作,有三種狀態:pending、fulfilled和rejected。只有非同步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態
  2. 一旦狀態改變,就不會再改變。Promise物件的狀態的改變只有兩種可能 從pending變為fulfilled和從pending變為rejected
    Promise--感性認知

2.實現要點

1.promise的呼叫方式是鏈式呼叫,每次then方法會生成一個新的Promise例項

2.每個Promise例項自身維護一個回撥處理處理佇列。

3.具體實現

1.promise 建構函式 這一步將初始化Promise內部狀態,並立即執行executor

function Promise(executor) {
  let self = this;
  self.status = 'pending';
  self.value = undefined;
  self.reason = undefined;
  self.onResolved = [];
  self.onRejected = [];
  try {
    executor(resolve, reject);
  } catch (e) {
    reject(e);
  }
}
複製程式碼

2.then函式

每次promise執行then後都會返回一個新的promise;每次返回新的Promise物件(因為promise狀態確定後 就是不能更改);then方方法中的成功或失敗是一個可選引數

  onfulfilled = typeof onfulfilled == 'function' ? onfulfilled : val => val;
  onrejected = typeof onrejected === 'function' ? onrejected : err => {
    throw err;
  }
  let self = this;

  let promise2;
  promise2 = new Promise((resolve, reject) => {
    if (self.status === 'resolved') {
      setTimeout(() => {
        try {
          let x = onfulfilled(self.value);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      }, 0);
    }
    if (self.status === 'rejected') {
      setTimeout(() => {
        try {
          let x = onrejected(self.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      }, 0);
    }
    if (self.status === 'pending') {
      self.onResolved.push(function () {
        setTimeout(() => {
          try {
            let x = onfulfilled(self.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      });
      self.onRejected.push(function () {
        setTimeout(() => {
          try {
            let x = onrejected(self.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      });
    }
  })
  return promise2;
複製程式碼

3.catch函式

catch 會捕獲到沒有捕獲的異常

    Promise.prototype.catch = function (onrejected) {
      return this.then(null, onrejected)
    }
複製程式碼

4.Promise相關方法實現

  1. Promise.resolve

    Promise.resolve(value)方法也會返回一個新的 Promise 例項,該例項的狀態為rejected。

     Promise.resolve = function (value) {
       return new Promise((resolve, reject) => {
         resolve(value);
       })
     }
    複製程式碼
  2. Promise.reject

    Promise.reject(reason)方法也會返回一個新的 Promise 例項,該例項的狀態為rejected。

     Promise.reject = function (reason) {
         return new Promise((resolve, reject) => {
         reject(reason)
         })
     }
    複製程式碼
  3. Promise.race

        const p = Promise.race([p1,p2,p3])
    複製程式碼

    Promise.race方法同樣是將多個 Promise 例項,包裝成一個新的 Promise 例項。 上面程式碼中,只要p1、p2、p3之中有一個例項率先改變狀態,p的狀態就跟著改變。那個率先改變的 Promise 例項的返回值,就傳遞給p的回撥函式

    Promise.race = function (promises) {
      return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; i++) {
          let p = promises[i];
          p.then(resolve, reject);
        }
      })
    }
    複製程式碼

4.Promise.all

Promise.all 方法用於將多個 Promise 例項,包裝成一個新的 Promise 例項。只有例項陣列中的例項狀態均變為 fulfilled,外層例項才會變成 fulfilled,此時例項陣列的返回值組成一個陣列,傳遞給外層例項的回撥函式。例項陣列中有一個被 rejected,外層例項的狀態就變成 rejected,此時第一個被 reject 的例項的返回值,會傳遞給外層例項的回撥函式。

    Promise.all = function (promises) {
      return new Promise((resolve, reject) => {
        let results = []; let i = 0;
        function processData(index, data) {
          results[index] = data;
          if (++i === promises.length) {
            resolve(results);
          }
        }
        for (let i = 0; i < promises.length; i++) {
          let p = promises[i];
          p.then((data) => {
            processData(i, data);
          }, reject);
        }
      })
    }
複製程式碼

結語

promise 可以解決回撥地獄的問題;多個非同步請求可以同步最終結果;程式碼寫起來更有流程感。 第一次寫文章,不太會寫,希望慢慢的會有進步,理解和思考問題也會更深層次。

相關文章