1. 程式人生 > >js實現promise

js實現promise

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>實現promise</title>
</head>
<body>
    <script>
        function MyPromise(executor){
  var that = this
  this.status = 'pending' // 當前狀態
  this.data = undefined
  this.onResolvedCallback = [] // Promise resolve時的回撥函式集,因為在Promise結束之前有可能有多個回撥新增到它上面
  this.onRejectedCallback = [] // Promise reject時的回撥函式集,因為在Promise結束之前有可能有多個回撥新增到它上面

  // 更改狀態 => 繫結資料 => 執行回撥函式集
  function resolve(value){
    if(that.status === 'pending'){
      that.status = 'resolved'
      that.data = value
      for(var i = 0; i < that.onResolvedCallback.length; ++i){
        that.onResolvedCallback[i](value)
      }
    }
  }

  function reject(reason){
    if(that.status === 'pending'){
      that.status = 'rejected'
      that.data = reason
      for(var i = 0; i < that.onResolvedCallback.length; ++i){
        that.onRejectedCallback[i](reason)
      }
    }
  }

  try{ 
    executor(resolve, reject) // resolve, reject兩個函式可以在外部傳入的函式(executor)中呼叫
  } catch(e) { // 考慮到執行過程可能有錯
    reject(e)
  }
}

// 標準是沒有catch方法的,實現了then,就實現了catch
// then/catch 均要返回一個新的Promise例項

MyPromise.prototype.then = function(onResolved, onRejected){
  var that = this
  var promise2

  // 值穿透
  onResolved = typeof onResolved === 'function' ? onResolved : function(v){ return v }
  onRejected = typeof onRejected === 'function' ? onRejected : function(r){ return r }

  if(that.status === 'resolved'){
    return promise2 = new MyPromise(function(resolve, reject){
      try{
        var x = onResolved(that.data)
        if(x instanceof MyPromise){ // 如果onResolved的返回值是一個Promise物件,直接取它的結果做為promise2的結果
          x.then(resolve, reject)
        }
        resolve(x) // 否則,以它的返回值做為promise2的結果 
      } catch(e) {
        reject(e) // 如果出錯,以捕獲到的錯誤做為promise2的結果
      }
    })
  }

  if(that.status === 'rejected'){
    return promise2 = new MyPromise(function(resolve, reject){
      try{
        var x = onRejected(that.data)
        if(x instanceof MyPromise){
          x.then(resolve, reject)
        }
      } catch(e) {
        reject(e)
      }
    })
  }

  if(that.status === 'pending'){
    return promise2 = new MyPromise(function(resolve, reject){
      self.onResolvedCallback.push(function(reason){
        try{
          var x = onResolved(that.data)
          if(x instanceof MyPromise){
            x.then(resolve, reject)
          }
        } catch(e) {
          reject(e)
        }
      })

      self.onRejectedCallback.push(function(value){
        try{
          var x = onRejected(that.data)
          if(x instanceof MyPromise){
            x.then(resolve, reject)
          }
        } catch(e) {
          reject(e)
        }
      })
    })
  }
}

MyPromise.prototype.catch = function(onRejected){
  return this.then(null, onRejected)
}

// 以下是簡單的測試樣例:
new MyPromise(resolve => resolve(2)).then(value => {
  console.log(value)
})
    </script>
</body>
</html>