当前位置: 首页 > article >正文

手写Promise源码的实现思路

Promise的使用:

let promise = new Promise((resolve, reject) => {
    resolve("OK");
    // reject("Error");
});

console.log(promise);

promise.then(value => {
    console.log("success");
}, error => {
    console.log("fail");
});
  1. 定义构造函数中的两个基本属性PromiseStatePromiseResult

    function Promise() {
        this.PromiseState = "pending";
        this.PromiseResult = null;
    }
    
  2. 由于实例对象中传递的参数是一个执行器函数,并且会立即执行这个函数。

    function Promise(executor) {
        this.PromiseState = "pending";
        this.PromiseResult = null;
        
        executor();
    }
    
  3. 该执行器函数中有两个函数参数,调用任意一个函数会改变promise的状态和结果值,且状态只能改变一次。

    function Promise(executor) {
        this.PromiseState = "pending";
        this.PromiseResult = null;
        
        // 防止this指向window
        const self = this;
        function resolve(value) {
            if(self.PromiseState !== "pending") return;
            self.PromiseState = "fulfilled";
            self.PromiseResult = value;
        }
        
        function reject(reason) {
            if(self.PromiseState !== "pending") return;
            self.PromiseState = "rejected";
            self.PromiseResult = reason;
        }
        // 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值
        executor(resolve, reject);
    }
    
  4. 还有一种情况:promise实例执行结果为抛出异常,需要让其状态为失败。

    function Promise(executor) {
        // ...
        
        // 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值;抛出异常时状态为失败
        try {
            executor(resolve, reject);
        } catch (error) {
            reject(error);
        }
    }
    
  5. 在对象原型上添加then方法。

    Promise.prototype.then = function(onResolved, onRejected) {
        if(this.PromiseState === "fulfilled") {
            onResolved();
        }
        if(this.PromiseState === "rejected") {
            onRejected();
        }
    }
    
  6. executor的执行内容是异步的,应该等到异步执行后改变了状态才能执行then中的回调函数,异步执行前状态还是为pending

    let promise = new Promise((resolve, reject) => {
        setTimeout(()=> {
            resolve("OK");
        }, 1000);
    });
    
    function Promise(executor) {
        // ...
        this.callback = null;
    
        // 防止this指向window
        const self = this;
        function resolve(value) {
            if(self.PromiseState !== "pending") return;
            self.PromiseState = "fulfilled";
            self.PromiseResult = value;
            if(self.callback.onResolved) {
                self.callback.onResolved();
            }
        }
        
        function reject(reason) {
            if(self.PromiseState !== "pending") return;
            self.PromiseState = "rejected";
            self.PromiseResult = reason;
            if(self.callback.onRejected) {
                self.callback.onRejected();
            }
        }
        // ...
    }
    
    // then方法
    Promise.prototype.then = function(onResolved, onRejected) {
        // ...
        if(this.PromiseState === "pending") {
            // 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来
            this.callback = {
                onResolved,
                onRejected
            };
        }
    }
    
  7. 当一个Promise实例执行了多个then方法时,两个then里的方法都会执行。

    let promise = new Promise((resolve, reject) => {
        resolve("OK");
    });
    
    promise.then(value => {
        console.log("success");
    }, error => {
        console.log("fail");
    });
    
    promise.then(value => {
        console.log("success2");
    }, error => {
        console.log("fail2");
    });
    // success success2
    
    function Promise(executor) {
        // ...
        this.callback = null;
    
        // 防止this指向window
        const self = this;
        function resolve(value) {
            if(self.PromiseState !== "pending") return;
            self.PromiseState = "fulfilled";
            self.PromiseResult = value;
            self.callbacks.forEach(item => {
                item.onResolved();
            });
        }
        
        function reject(reason) {
            if(self.PromiseState !== "pending") return;
            self.PromiseState = "rejected";
            self.PromiseResult = reason;
            self.callbacks.forEach(item => {
                item.onRejected();
            });
        }
        // ...
    }
    
    // then方法
    Promise.prototype.then = function(onResolved, onRejected) {
        // ...
        if(this.PromiseState === "pending") {
            // 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来
            this.callbacks.push({
                onResolved,
                onRejected
            });
        }
    }
    
  8. then方法返回的也是一个Promise实例,这个实例的状态由执行的回调函数的结果来决定,如果回调函数的执行内容是非Promise实例,则都为成功状态;如果是Promise实例,状态根据这个实例的状态来定。

    • executor执行内容为同步时:

      Promise.prototype.then = function(onResolved, onRejected) {
          const self = this;
          return new Promise((resolve, reject) => {
              if(self.PromiseState === "fulfilled") {
                  // 拿到回调函数的返回值
                  // Promise实例:根据其结果状态决定then执行后该实例的状态;非Promise实例:状态都为成功
                  const result = onResolved(self.PromiseResult);
                  if(result instanceof Promise) {
                      // 既然是一个Promise实例,就能根据该实例的执行内容确定状态
                      result.then(v => {
                          resolve(v);
                      }, r => {
                          reject(r);
                      });
                  } else {
                      resolve(result);
                  }
              }
              if(self.PromiseState === "rejected") {
                  // 同上
                  const result = onRejected(self.PromiseResult);
                  if(result instanceof Promise) {
                      result.then(v => {
                          resolve(v);
                      }, r => {
                          reject(r);
                      });
                  } else {
                      resolve(result);
                  }
              }
              }
              // ...
          })
      }
      
    • executor执行内容为异步时:

      Promise.prototype.then = function(onResolved, onRejected) {
          const self = this;
          return new Promise((resolve, reject) => {
              // ...
              if(self.PromiseState === "pending") {
                  // 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来
                  self.callbacks.push({
                      onResolved: function() {
                          // 同上
                          const result = onResolved(self.PromiseResult);
                          if(result instanceof Promise) {
                              result.then(v => {
                                  resolve(v);
                              }, r => {
                                  reject(r);
                              });
                          } else {
                              resolve(result);
                          }
                      },
                      onRejected: function() {
                          // 同上
                          const result = onRejected(self.PromiseResult);
                          if(result instanceof Promise) {
                              result.then(v => {
                                  resolve(v);
                              }, r => {
                                  reject(r);
                              });
                          } else {
                              resolve(result);
                          }
                      }
                  });
              }
          })
      }
      
  9. 封装then方法中出现的重复代码,并处理

    Promise.prototype.then = function(onResolved, onRejected) {
        const self = this;
        return new Promise((resolve, reject) => {
            // 封装函数:根据结果改变状态
            function callback(fn) {
                try {
                    // 拿到回调函数的返回值
                    // Promise实例:根据其结果状态决定then执行后该实例的状态;非Promise实例:状态都为成功
                    let result = fn(self.PromiseResult);
                    if(result instanceof Promise) {
                        // 既然是一个Promise实例,就能根据该实例的执行内容确定状态
                        result.then(v => {
                            resolve(v);
                        }, r => {
                            reject(r);
                        });
                    } else {
                        resolve(result);
                    }
                } catch (error) {
                    reject(error);
                }
            }
    
            if(self.PromiseState === "fulfilled") {
                callback(onResolved);
            }
            if(self.PromiseState === "rejected") {
                callback(onRejected);
            }
            if(self.PromiseState === "pending") {
                // 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来
                self.callbacks.push({
                    onResolved: function() {
                        callback(onResolved);
                    },
                    onRejected: function() {
                        callback(onRejected);
                    }
                });
            }
        })
    }
    
  10. 添加catch方法并实现异常穿透,同时实现then只传递一个参数和不传递参数的情况。

    // 使用
    promise.then(value => {
        return new Promise((resolve, reject) => {
            reject("111 error")
        })
    }).then((value) => {
        console.log(222)
    }).catch(err => {
        console.log("err-------------")
        console.log(err)
    });
    
    // then方法
    Promise.prototype.then = function(onResolved, onRejected) {
        const self = this;
        // 不传第二个函数时,默认函数为一个抛出异常操作
        if(typeof onRejected !== "function") {
            onRejected = reason => {
                throw reason;
            }
        }
        // 不传第一个函数时,默认将实例结果值返回,可以实现成功时的值传递
        if(typeof onResolved !== "function") {
            onResolved = value => value;
        }
    
        return new Promise((resolve, reject) => {
            // ...
        })
    }
    
    // catch方法
    Promise.prototype.catch = function(onRejected) {
        return this.then(undefined, onRejected);
    }
    
  11. 添加Promise.resolvePromisereject方法。

    // resolve方法:根据传入参数的类型决定结果的状态
    Promise.resolve = function(value) {
        return new Promise((resolve, reject) => {
            if(value instanceof Promise) {
                // 既然是一个Promise实例,就能根据该实例的执行内容确定状态
                value.then(v => {
                    resolve(v);
                }, r => {
                    reject(r);
                });
            } else {
                resolve(value);
            }
        })
    }
    
    // reject方法:无论传入的参数是什么类型,结果都是失败状态
    Promise.reject = function(reason) {
        return new Promise((resolve, reject) => {
            reject(reason);
        })
    }
    
  12. 添加Promise.all方法:所有实例都成功则为成功,结果值为所有实例结果值组成的数组;有一个失败,则为失败,结果值为失败的实例的结果值。

    Promise.all = function(promises) {
        return new Promise((resolve, reject) => {
            let count = 0,
                resultArr = [];
            promises.forEach((item, index) => {
                item.then(v => {
                    count++;
                    // 按实例的索引值存储其对应结果
                    resultArr[index] = item.PromiseResult;
                    // 全部都为成功时为成功
                    if(count === promises.length) {
                        resolve(resultArr);
                    }
                }, r => {
                    reject(r);
                });
            });
        })
    }
    
  13. 添加Promise.race方法:实例中谁先改变状态,返回的状态和结果值就为该实例的状态和结果值。

    Promise.race = function(promises) {
        return new Promise((resolve, reject) => {
            promises.forEach(item => {
                item.then(v => {
                    resolve(v);
                }, r => {
                    reject(r);
                });
            });
        })
    }
    
  14. then方法是一个异步任务。

    function Promise(executor) {
        // ...
    
        // 防止this指向window
        const self = this;
        function resolve(value) {
            // ...
            setTimeout(() => {
                self.callbacks.forEach(item => {
                    item.onResolved();
                });
            });
        }
        
        function reject(reason) {
            // ...
            setTimeout(() => {
                self.callbacks.forEach(item => {
                    item.onRejected();
                });
            });
        }
        // 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值;抛出异常时状态为失败
        try {
            executor(resolve, reject);
        } catch (error) {
            reject(error);
        }
    }
    
    // then方法
    Promise.prototype.then = function(onResolved, onRejected) {
        // ...
    
        return new Promise((resolve, reject) => {
            // ...
            
            if(self.PromiseState === "fulfilled") {
                setTimeout(() => {
                    callback(onResolved);
                });
            }
            if(self.PromiseState === "rejected") {
                setTimeout(() => {
                    callback(onRejected);
                });
            }
            // ...
        })
    }
    

调整一下代码结构,整个promise.js源码如下:

function Promise(executor) {
    this.PromiseState = "pending";
    this.PromiseResult = null;
    this.callbacks = [];

    // 防止this指向window
    const self = this;
    function resolve(value) {
        if(self.PromiseState !== "pending") return;
        self.PromiseState = "fulfilled";
        self.PromiseResult = value;
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onResolved();
            });
        });
    }
    
    function reject(reason) {
        if(self.PromiseState !== "pending") return;
        self.PromiseState = "rejected";
        self.PromiseResult = reason;
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onRejected();
            });
        });
    }
    // 参数为一个函数且立即执行,该函数需要两个函数参数改变promise的状态和结果值;抛出异常时状态为失败
    try {
        executor(resolve, reject);
    } catch (error) {
        reject(error);
    }
}

// then方法
Promise.prototype.then = function(onResolved, onRejected) {
    // 不传第一个函数时,默认将实例结果值返回,可以实现成功时的值传递
    if(typeof onResolved !== "function") {
        onResolved = value => value;
    }
    // 不传第二个函数时,默认函数为一个抛出异常操作
    if(typeof onRejected !== "function") {
        onRejected = reason => {
            throw reason;
        }
    }

    const self = this;
    return new Promise((resolve, reject) => {
        // 封装函数:根据结果改变状态
        function callback(fn) {
            try {
                // 拿到回调函数的返回值
                // Promise实例:根据其结果状态决定then执行后该实例的状态;非Promise实例:状态都为成功
                let result = fn(self.PromiseResult);
                if(result instanceof Promise) {
                    // 既然是一个Promise实例,就能根据该实例的执行内容确定状态
                    result.then(v => {
                        resolve(v);
                    }, r => {
                        reject(r);
                    });
                } else {
                    resolve(result);
                }
            } catch (error) {
                reject(error);
            }
        }

        if(self.PromiseState === "pending") {
            // 此时还未改变promise的状态,回调函数无法立即执行,只能先保存下来
            self.callbacks.push({
                onResolved: function() {
                    callback(onResolved);
                },
                onRejected: function() {
                    callback(onRejected);
                }
            });
        } else if(self.PromiseState === "fulfilled") {
            setTimeout(() => {
                callback(onResolved);
            });
        } else if(self.PromiseState === "rejected") {
            setTimeout(() => {
                callback(onRejected);
            });
        }
        
    })
}

// catch方法
Promise.prototype.catch = function(onRejected) {
    return this.then(undefined, onRejected);
}

// resolve方法:根据传入参数的类型决定结果的状态
Promise.resolve = function(value) {
    return new Promise((resolve, reject) => {
        if(value instanceof Promise) {
            // 既然是一个Promise实例,就能根据该实例的执行内容确定状态
            value.then(v => {
                resolve(v);
            }, r => {
                reject(r);
            });
        } else {
            resolve(value);
        }
    })
}

// reject方法:无论传入的参数是什么类型,结果都是失败状态
Promise.reject = function(reason) {
    return new Promise((resolve, reject) => {
        reject(reason);
    })
}

// all方法
Promise.all = function(promises) {
    return new Promise((resolve, reject) => {
        let count = 0,
            resultArr = [];
        promises.forEach((item, index) => {
            item.then(v => {
                count++;
                // 按实例的索引值存储其对应结果
                resultArr[index] = item.PromiseResult;
                // 全部都为成功时为成功
                if(count === promises.length) {
                    resolve(resultArr);
                }
            }, r => {
                reject(r);
            });
        });
    })
}

// race方法
Promise.race = function(promises) {
    return new Promise((resolve, reject) => {
        promises.forEach(item => {
            item.then(v => {
                resolve(v);
            }, r => {
                reject(r);
            });
        });
    })
}

http://www.kler.cn/a/2895.html

相关文章:

  • 重温设计模式--迭代器模式
  • 命令手动更新 Navigator
  • 写作词汇积累:见笑、尽显、稀疏、染指
  • StartAI图生图局部重绘,让画面细节焕发新生!!
  • C++ Learning string类的使用
  • 【目标跟踪综述及关键技术】
  • vue 高德地图添加放大缩小地图、转盘工具
  • 【模拟】日期问题、回文日期思路详解及代码实现
  • 静态通讯录,适合初学者的手把手一条龙讲解
  • 【java基础】Stream流的各种操作
  • 系统集成路由器OSPF动态、综合路由配置
  • 基于SpringBoot的酒店管理系统
  • 机器学习笔记之前馈神经网络(三)M-P神经元模型与感知机的关系
  • ElementUI学习笔记
  • 面试问了解Linux内存管理吗?10张图给你安排的明明白白
  • Linux编辑器-vim
  • 快速上手vue elementUI好看的登录界面
  • 嵌入式学习笔记——SysTick(系统滴答)
  • Mybatis(三):特殊SQL的执行
  • ChatGPT来了你慌了吗?
  • JavaScript到底如何存储数据?
  • 网络安全工程师做什么?
  • 四级数据库工程师 刷真题错题整理(三)数据库原理
  • 排好队,一个一个来:宫本武藏教你学队列(附各种队列源码)
  • Java入门知识(超详细讲解)
  • VSCode嵌入式开发环境搭建