【ES6系列】Promise

Promise 基本用法(Promise Syntax):new Promise( function(resolve, reject) {…} );

通過創建 Promise 對象開啓一個異步操作的過程,一般用幾步完成多次異步操作:

  1. new Promise(fn) 返回一個Promise 對象
  2. 在fn 中指定異步等處理
  3. 處理結果正常的話,調用resolve(處理結果值)
  4. 處理結果錯誤的話,調用reject(Error對象)
function loadScript(src) {
  return new Promise((resolve, reject) => {
    let script = document.createElement('script')
    script.src = src
    script.onload = () => resolve(src)
    script.onerror = (err) => reject(err)
    document.head.append(script)
  })
}
loadScript('./1.js')
  .then(loadScript('./2.js'))
  .then(loadScript('./3.js'))

Promise 內部狀態(pending、fulfilled、rejected),Promise 對象根據狀態來確定執行哪個方法。Promise 在實例化的時候狀態默認爲 pending,當異步操作完成,狀態會被修改爲 fulfilled,當異步操作遇到異常,狀態會被修改爲 rejected。而此種狀態變化是單向且不可逆轉的,已經確定的狀態(fulfilled/rejected)無法轉回初始狀態(pending),而且只能是從 pending 到 fulfilled 或者 rejected

串行異步操作——Promise.prototype.then():then 是 promise 原型上的方法,只有promise可以調用then

基本語法:promise.then(onFulfilled, onRejected):then 支持兩個參數,這兩個參數都是函數類型,第一個參數必選,第二個參數可選。這兩個函數分別對應是 Promise 對象的resolve 和 reject 這兩個方法,如果傳入的這兩個參數是非函數或被遺漏,會返回一個空的 promise 對象,以保證只要調用 promise 對象就一定可以返回一個 promise 對象,所以可以鏈式調用 .then()

寫法改造:

function loadScript(src) {
  return new Promise((resolve, reject) => {
    let script = document.createElement('script')
    script.src = src
    script.onload = () => resolve(src)
    script.onerror = (err) => reject(err)
    document.head.append(script)
  })
}
loadScript('./1.js')
  .then(() => {
    return loadScript('./4.js') // 返回 promise 對象影響下一個.then()
  }, (err) => {
    console.log(err)
  })
  .then(() => {
    loadScript('./3.js')
  }, (err) => {
    console.log(err)
  })

Promise.resolve() 和 Promise.reject() 是 Promise 的靜態方法,是 new Promise() 方法的快捷方式。

Promise.prototype.catch(),用 Promise 對象的 catch 方法來捕獲異步操作過程中出現的任何異常,當 promise 狀態改爲rejected時捕獲錯誤。

 new Error 不會觸發 catch,而是 reject,不建議在 Promise 內部使用 throw 來觸發異常,而是使用 reject(new Error()) 的方式來做,因爲 throw 的方式並沒有改變 Promise 的狀態

並行異步操作——Promise.all():滿足所有任務都完成的條件

生成並返回一個新的 Promise 對象,所以它可以使用 Promise 實例的所有方法。參數傳遞promise數組中所有的 Promise 對象都變爲resolve的時候,該方法纔會返回, 新創建的 Promise 則會使用這些 promise 的值。如果參數中的任何一個promise爲reject的話,則整個Promise.all調用會立即終止,並返回一個reject的新的 Promise 對象。由於參數數組中的每個元素都是由 Promise.resolve 包裝(wrap)的,所以Paomise.all 可以處理不同類型的 promose對象。

const p1 = Promise.resolve(1) //使用Promise進行一個異步操作,返回結果是1
const p2 = Promise.resolve(2)
const p3 = Promise.resolve(3)
Promise.all([p1, p2, p3]).then((value) => {
  console.log(value) //[1, 2, 3]
})

Promise.race():先到先得

Promise.race 生成並返回一個新的 Promise 對象。參數 promise 數組中的任何一個 Promise 對象如果變爲 resolve 或者 reject 的話, 該函數就會返回,並使用這個 Promise 對象的值進行 resolve 或者 reject。

思考:

1、按順序加載腳本太直觀看出順序執行的過程,如果按順序延時執行是不是更好理解?

2、請用 Promise 實現一個接口。

const p1 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      resolve(1)
    }, 1000)
  })
}

const p2 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      resolve(2)
    }, 0)
  })
}
Promise.race([p1(), p2()]).then((value) => {
  console.log(value) // 2
})

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章