promise 专题

promise 基本概念

  • promise 是一个构造函数, 必须传一个 executor 执行器
  • executor 会立刻执行,并传入 resolve 和 reject 参数
  • promise 三种状态: fulfilled成功 reject 失败 pending等待
  • 可以通过 resolve 和 reject 来改变状态, 同时调用对应的回调
    • 一个 promise 实例状态改变后,不能再重新发生新的变化
  • 当 executor 有异常时,也会触发 promise 的失败 (reject)

通过上方的描述 我们来构建最基本的代码框架

const FULFILLED = "FULFILLED"
const REJECTED = "REJECTED"
const PENDING = "PENDING"

class Promise {
   constructor(executor){
       this.state = PENDING; // promise 的状态,默认是 PENDING
       this.value = null;  // 成功状态的接受参数
       this.reason = null; // 失败后状态的参数
       this.onFulfilledCallbasks = []; // 异步状态下成功的回调函数集合
       this.onRejectedCallbacks = [];  // 异步状态下失败的回调函数几个
       const resolve = (value)=>{ // 成功后调用的函数
           if(this.state === PENDING){ // 防止一次promise触发多个状态
               this.state = FULFILLED; // 将状态改为成功
               this.value = value; //将成功的内容赋值给 value 变量,供给 then 调用
               this.onFUliflledCallbasks.forEach(item=>{item()}) // j执行异步的回调队列
          }
      }
       const reject = (reason)=>{ // 失败后调用的函数
            if(this.state === PENDING){
               this.state = REJECTED; // 将状态改为失败
               this.reason = reason; // 将失败的内容赋值给 reason 变量,供给 then 调用
                this.onRejectedCallbasks.forEach(item=>{item()} //执行异步回调的队列
          }
      }
       try{
           exectuor(resolve,reject) // exectuor会立即执行,传入resolve,reject两个参数
      }catch(err){
           reject(err) // 如果 exectuor发生异常则直接 reject
      }
  }
       
   then(onFulfilled,onRejected){ // 接收一个成功 , 失败的回调
       let promise2 = new Promise((resolve,reject)=>{
           if(this.state === FULFILLED){ // 如果吃成功状态,则调用resolve
               let x = onFulfilled(this.value)
               resolve(x)
          }
           if(this.state === REJECTED){ // 如果是失败状态,则调用reject
               let x = onRejected(this.reason)
               reject(x)
          }
           if(this.state === PENDING){
               this.onFulfilledCallbacks.push(()=>{ // 异步的成功回调
                   let x = onFulfilled(this.value)
              resolve(x)
              })
               this.onRejectedCallbacks,push(()=>{ // 异步的失败回调
                   let x = onRejected(this.reason)
              reject(x)
              })
          }
      })
  }
}
export default Promise

then 链的特点

  • 当 then 中成功和失败的回调返回一个 promise 时,内部会解析和这个 promise, 并且将结果传递给外层的下一个 then
  • 下一次 then 的成功和失败,取决于当前的 promise 状态
  • 如果成功和失败返回的不是一个 promise ,则直接给下一个 then 的成功
  • 如果成功和失败的回调出现异常,则直接传递给下一个 then 的失败

resolvePromise 实现逻辑

判断 then 的输入方式,需要单独封装一个 resolvePromise 函数进行链路判断和引导

规范

resolvePromise共接收四个参数 promise , x , resolve , reject

  • 如果 x 和 promise2 引用的是同一个对象就会造成死循环, 需要 reject 直接抛出异常
  • 判断 x 是否为 promise
    • 缩小范围 (x===”object” && x !== null) || (x === “function”)
    • 查看 x 有没有 .then 属性 (规范中: 取出 x.then 可能会发生异常, 如果 then 是 function 则就认定他是 promise)
  • 如果 x 是 promise 则监听报错
    • try 优化, 防止 x.then 的返回是同一个 promise, 必须调用 resolvePromise
    • 防止多一次调用多个状态, 加入 called 认证, 只要通过一个状态,这个值就会认为 true
function resolvePromise (promise2,x,resolve,reject){
   // 判断 x 和 promise 不能引入同一个 promise 对象
   if(promise2 === x){reject(new TypeError("chaining cycle detected for promise"))}
   // 判断 x 是不是 promise 对象
   if((typeof x === "object" && x !== null) || (typeof x === "function")){
       let called = false; // 防止出现一个回调执行多个状态
       try{
           let then = x.then;
           if(typeof then === "function"){
               then.call(
              x,
                  (y)=>{
                      if(called){return}
                       called = true;
                       resolvePromise(promise2,y,resolve,reject)
                  },
                  (err)=>{
                       if(called){return}
                       called = true;
                       reject(err)
                  }
              )
          }else{
               resolve(x)
          }
      }catch(err){
           if(called){return}
           called = true;
           reject(err)
      }
  }else{
       resolve(x)
  }
}

class promise {
   ....
   then(onFulfilled,onRejected){ // 接收一个成功 , 失败的回调
       let promise2 = new Promise((resolve,reject)=>{
           if(this.state === FULFILLED){ // 如果吃成功状态,则调用resolve
               try{
                   let x = onFulfilled(this.value)
                   resolvePromise(promise2,x,resolve,reject)
              }catch(error){
                reject(error)
              }
          }
           if(this.state === REJECTED){ // 如果是失败状态,则调用reject
               try{
                   let x = onRejected(this.reason)
                   resolvePromise(promise2,x,resolve,reject)
              }catch(error){
                   reject(error)
              }
          }
           if(this.state === PENDING){
               this.onFulfilledCallbacks.push(()=>{ // 异步的成功回调
                   try{
                       let x = onFulfilled(this.value)
              resolvePromise(promise2,x,resolve,reject)
                  }catch(error){
                      reject(error)
                  }
              })
               this.onRejectedCallbacks,push(()=>{ // 异步的失败回调
                   try{
                       let x = onFulfilled(this.value)
              resolvePromise(promise2,x,resolve,reject)
                  }catch(error){
                    reject(error)  
                  }
              })
          }
      })
  }
}

then 的优化

class Promise{
   ...
   then(onFulfilled,onRejected){
       onFulilled = typeof onFulfilled === "function"?onFulflled : v=>v;
       onRejected = typeof onRejected === "function"? onRejected : e=>{throw e}
  }
}

常用API实现

promise.catch

失败的回调

用法

let xxx = new Promise((resolve,reject)=>{})
xxx.then(()=>{}).catch(()=>{})

实现

class Promise{
   ...
   static catch = function (errCallback){
       return this.then(null,errCallback)
  }
}

promise.resolve

class Promise {
   constructor(exectuor){
       ...
       const resolve = (value)=>{
          // 判断value是不是 promise ,如果是直接返回then的结果
          if(value === Promise){
             return value.then(resolve,reject)
          }
           ...
      }
       ...
  }
   static resolve= function(value){
       return new Promise((resolve,reject)=>{
           resolve(value)
      })
  }
}

promise.reject

class Promise{
   static reject = function(reason){
       return new Promise((resolve,reject)=>{
           reject(reason)
      })
  }
}

promise.call

只有全部成功才会成功

用法

new Promise.call([promise1,promise2]).then(()=>{},()=>{})

实现

class Promise{
   static all(values){
       return new Promise((resolve,reject)=>{
          let arr = [];
      let times = 0;
           function processData(index,data){
               arr[index] = data;
               if(++times === values.length){
                   resolve(arr)
              }
          }
           values.forEach((item,index)=>{
               Promise.resolve(item).then(()=>{
processDate(index,data)                    
              })
          })
      })
  }
}

promise.race

有一个成功就算成功

class Promise{
   static race = function(values){
       return new Promise((resolve,reject)=>{
           values.forEach((item)=>{
               Promise.resolve(item).then(resolve,reject)
          })
      })
  }
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇