Skip to content

目录

  • 一、介绍
  • 二、初始结构
    • promise三个状态及结果
  • 三、then
    • 1、then参数问题
    • 2、throw Error问题
    • 3、Promise不加异步执行顺序
    • 4、Promise加异步执行顺序
    • 5、返回Promise对象
  • 四、Promise链式操作
  • 完整代码

一、介绍

JavaScript Promise 是一种异步编程的解决方案,可以更好地管理和组织异步代码。 Promise 提供了一种更简洁和直观的方法来处理异步操作,而不必依赖于回调函数。

二、初始结构

Promise 是一个对象,表示一个异步操作的最终完成(或失败)及其结果值。Promise 可以有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。当 Promise 对象的状态从 pending 转变为 fulfilled 或 rejected 时,表示异步操作已经完成。以下是一个使用 Promise 的简单示例:

正常我们写代码是这样的。

js
new Promise((resolve,reject) => {
  resolve("learn promise success!");
  reject("learn promise error!");
}).then( res => {
  console.log(res);
})

根据promise用法和看它源码分析。首先promise会有resolve、reject、then、catch主要方法。这里就只写基础版本,所以得到下面,我们需要去接收外面传进来参数。

js
/**
 * Promise 构造函数
 * @param {Function} executor - 执行器函数
 */
class MyPromise {
  constructor(executor){
    // 将 resolve 函数绑定到 Promise 实例上
    this.resolve = (result) => {
      // learn promise success!
      console.log(result,"result")
    }
    // 将 reject 函数绑定到 Promise 实例上
    this.reject = (error) => {
      // learn promise error!
      console.log(error,"error")
    }
    // 执行器函数接受 resolve 和 reject 函数作为参数
    executor(this.resolve, this.reject);
  }
  then(){
  }
  catch(){
  }
}

上面结果是无法打印的。因为MyPromise里面的then没有去给他返回。

promise三个状态及结果

因为promise有三个状态所以我们,分为不同状态,并把状态和结果保存下来。

js
class SelfPromise {
    static PADDIBNG = "等待";
    static FULILLED = "成功";
    static REJECT = "拒绝";
    constructor(executor) {
    // 存储 Promise 状态
    this.PromiseState = SelfPromise.PADDIBNG;
    // 存储 Promise 结果
    this.PromiseResult = null;
    this.resolve = (result) => {
      if(this.PromiseState === SelfPromise.PADDIBNG){
        // 更新状态
        this.PromiseState = SelfPromise.FULILLED;
        // 存储结果
        this.PromiseResult = result;
      }
    };
    // 将 reject 函数绑定到 Promise 实例上
    this.reject = (error) => {
      if(this.PromiseState === SelfPromise.PADDIBNG){
        // 更新状态
        this.PromiseState = SelfPromise.REJECT;
        // 存储结果
        this.PromiseResult = error;
      }
    };
    // 执行器函数接受 resolve 和 reject 函数作为参数
    executor(this.resolve, this.reject);
}
then(onFulfilled, onRejected) {
}
  catch() {}
}

三、then

接下来,我们改写then啦。需要判断对任务处理状态,返回不同的数据

js
class SelfPromise {
  +
  +
  +
  then(onFulfilled, onRejected) {
    if(this.PromiseState === SelfPromise.FULILLED){
      onFulfilled(this.PromiseResult)
    }
    if(this.PromiseState === SelfPromise.REJECT){
      onRejected(this.PromiseResult)
    }
  }
  catch() {}
}

1、then参数问题

有一点需要注意的是。Promise。then是有两个参数的。所以通过不同状态返回对应结果。

js
new SelfPromise((resolve,reject) => {
  resolve("learn promise success11!");
  reject("learn promise error11!");
}).then( 
  res => console.log(res),
  err => console.log(err)
 )

如果我们不传两个正常函数可不可以呢,测试了Promise,它并不会抱错。

js
new Promise((resolve,reject) => {
 resolve("learn promise success11!");
 reject("learn promise error11!");
}).then( 
 undefined,
 err => console.log(err)
)

但是我们的会,所以需要处理一下,如果不是传的函数,我们需要给它一个默认函数。

js
class SelfPromise {
 +
 +
 +
 then(onFulfilled, onRejected) {
   onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
   onRejected = typeof onRejected === 'function' ? onRejected : () => {};
   if(this.PromiseState === SelfPromise.FULILLED){
     onFulfilled(this.PromiseResult)
   }
   if(this.PromiseState === SelfPromise.REJECT){
     onRejected(this.PromiseResult)
   }
 }
 catch() {}
}

2、throw Error问题

有时候,我们会像下面这样去做,去看了一下Promise,他没有抱错,只是会输出错误信息

js
new Promise((resolve,reject) => {
  throw new Error("不能随便使用啦!")
}).then( 
  res => console.log(res),
  err => console.log(err)
 )

但是当前我们代码会抱错,直接扔出错误,导致无法使用,所以我们需要对执行器处理一下。

js
class SelfPromise {
 constructor(){
 +
 +
 try {
     // 执行器函数接受 resolve 和 reject 函数作为参数
     executor(this.resolve, this.reject);
   } catch (error) {
     this.reject(error)
   }
 }  
 +
 +
}

3、Promise不加异步执行顺序

这个时候我们的程序是没有加任何异步的代码,例如常用的setTimeOut都没有用,可以说现在代码还是同步的,我们了解原生Promise的运行顺序规则,接下来为原生代码添加步骤信息。

js
console.log("第一步")
new Promise((resolve,reject) => {
    console.log("第二步")
    resolve("执行");
}).then( 
    res => console.log(res),
    err => console.log(err)
)
console.log("第三步")

// 执行顺序结果
第一步
第二步
第三步
执行

再来看看手写的。

js
console.log("第一步")
new SelfPromise((resolve,reject) => {
    console.log("第二步")
    resolve("执行");
}).then( 
    res => console.log(res),
    err => console.log(err)
)
console.log("第三步")
// 执行顺序结果
第一步
第二步
执行
第三步

发现顺序不同,这是哪里问题,其实就是因为没有设置异步代码原因,我们给then添加setTimeOut

js
class SelfPromise {
 +
 +
 +
 then(onFulfilled, onRejected) {
   onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
   onRejected = typeof onRejected === 'function' ? onRejected : () => {};
   if(this.PromiseState === SelfPromise.FULILLED){
     onFulfilled(this.PromiseResult)
   }
   if(this.PromiseState === SelfPromise.REJECT){
     onRejected(this.PromiseResult)
   }
 }
 catch() {}
}

再执行,顺序就对了。

4、Promise加异步执行顺序

接下来我们再给原生Promise添加异步

js
console.log("第一步")
new Promise((resolve,reject) => {
  console.log("第二步")
  setTimeout(() => {
    resolve("执行");
    console.log("第四步")
  });
}).then( 
  res => console.log(res),
  err => console.log(err)
)
console.log("第三步")
// 执行顺序结果
第一步
第二步
第三步
第四步
执行

接下来给手写代码添加异步

js
console.log("第一步")
new SelfPromise((resolve,reject) => {
  console.log("第二步")
  setTimeout(() => {
    resolve("执行");
    console.log("第四步")
  });
}).then( 
  res => console.log(res),
  err => console.log(err)
)
console.log("第三步")
// 执行顺序结果
第一步
第二步
第三步
第四步

通过调试发现,是因为.then没有执行onFulfilled,所以无法输出,刚刚的条件没有满足那两项。还缺少“等待”的状态

js
class SelfPromise {
  +
  +
  +
  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
    onRejected = typeof onRejected === 'function' ? onRejected : () => {};
    if(this.PromiseState === SelfPromise.PADDIBNG){

    }
    if(this.PromiseState === SelfPromise.FULILLED){
      onFulfilled(this.PromiseResult)
    }
    if(this.PromiseState === SelfPromise.REJECT){
      onRejected(this.PromiseResult)
    }
  }
  catch() {}
}

那等待的期间我们应该做些什么呢,因为这个时候任务还在执行中,等他异步任务处理,等异步处理完之后,执行resolve之后再来执行then,为了保留then里面的函数,我们创建callbacks数组来保存函数。等执行resolve的之后再去执行数组里面的then的回调。

js
class SelfPromise {
  static PADDIBNG = "等待";
  static FULILLED = "成功";
  static REJECT = "拒绝";
  constructor(executor) {
      // 存储 Promise 状
      this.PromiseState = SelfPromise.PADDIBNG;
      // 存储 Promise 结果
      this.PromiseResult = null;
      + // 存储 Promise 回调函数
      + this.callbacks = [];
      this.resolve = (result) => {
        if(this.PromiseState === SelfPromise.PADDIBNG){
          // 更新状态
          this.PromiseState = SelfPromise.FULILLED;
          // 存储结果
          this.PromiseResult = result;
          + // 执行回调函数
          + this.callbacks.forEach((callback) => callback.onFulfilled(result));
        }
      };
      // 将 reject 函数绑定到 Promise 实例上
      this.reject = (error) => {
        if(this.PromiseState === SelfPromise.PADDIBNG){
          // 更新状态
          this.PromiseState = SelfPromise.REJECT;
          // 存储结果
          this.PromiseResult = error;
          // 执行回调函数
          this.callbacks.forEach((callback) => callback.onRejected(result));
        }
      };
      try {
          // 执行器函数接受 resolve 和 reject 函数作为参数
          executor(this.resolve, this.reject);
      } catch (error) {
          this.reject(error)
      }
  }
  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
    onRejected = typeof onRejected === 'function' ? onRejected : () => {};
    + if(this.PromiseState === SelfPromise.PADDIBNG){
      + this.callbacks.push({
      +  onFulfilled,
      +  onRejected,
      +})
    +}
    if(this.PromiseState === SelfPromise.FULILLED){
      setTimeout(()=>{
        onFulfilled(this.PromiseResult)
      })
    }
    if(this.PromiseState === SelfPromise.REJECT){
      setTimeout(()=>{
        onRejected(this.PromiseResult)
      })
    }
  }
  catch() {}
}

但是我们发现还是不行,执行顺序还是没有变化。同理,我们给resolve、reject添加setTimeOut。

js
class SelfPromise {
 constructor(){
 +
 +
 this.resolve = (result) => {
   setTimeout(() => {
     if(this.PromiseState === SelfPromise.PADDIBNG){
       // 更新状态
       this.PromiseState = SelfPromise.FULILLED;
       // 存储结果
       this.PromiseResult = result;
       // 执行回调函数
       this.callbacks.forEach((callback) => callback.onFulfilled(result));
   }
});
};
// 将 reject 函数绑定到 Promise 实例上
this.reject = (error) => {
setTimeout(() => {
   if(this.PromiseState === SelfPromise.PADDIBNG){
       // 更新状态
       this.PromiseState = SelfPromise.REJECT;
       // 存储结果
       this.PromiseResult = error;
       // 执行回调函数
       this.callbacks.forEach((callback) => callback.onRejected(result));
     }
   });
 };
 +
 +
}

这样,顺序就对啦。

5、返回Promise对象

打印原生Promise

js
const P = new Promise((resolve,reject) => {
    resolve("执行");
}).then(()=>{})
console.log(P); // Promise {<pending>}

打印手写Promise

js
const P = new SelfPromise((resolve,reject) => {
    resolve("执行");
}).then(()=>{})
console.log(P); // undefined

所以我们知道then是要返回new SelfPromise对象的。所以这样改。

js
class SelfPromise {
  constructor(){
  +
  +
then(onFulfilled, onRejected) {
  return new SelfPromise((resolve, reject) => {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
    onRejected = typeof onRejected === 'function' ? onRejected : () => {};
    if(this.PromiseState === SelfPromise.PADDIBNG){
      this.callbacks.push({
        onFulfilled,
        onRejected,
      })
    }
    if(this.PromiseState === SelfPromise.FULILLED){
      setTimeout(()=>{
          onFulfilled(this.PromiseResult)
      })
    }
    if(this.PromiseState === SelfPromise.REJECT){
      setTimeout(()=>{
          onRejected(this.PromiseResult)
      })
    }
  })
}
  +
  +
}

再来看结果

js
const P = new SelfPromise((resolve,reject) => {
    resolve("执行");
}).then(()=>{})
console.log(P); 
// SelfPromise {PromiseState: '等待', PromiseResult: null, callbacks: Array(0), resolve: ƒ, reject: ƒ}

四、Promise链式操作

对原生Promise链式操作

js
const P = new Promise((resolve,reject) => {
    resolve("执行");
}).then( 
    res => console.log(res,"then1"),
    err => console.log(err)
).then( 
    res => console.log(res,"then2"),
    err => console.log(err)
).then( 
    res => console.log(res,"then3"),
    err => console.log(err)
)
// 结果
执行 then1
undefined 'then2'
undefined 'then3'

对手写Promise链式操作

js
const P = new Promise((resolve,reject) => {
    resolve("执行");
}).then( 
    res => console.log(res,"then1"),
    err => console.log(err)
).then( 
    res => console.log(res,"then2"),
    err => console.log(err)
).then( 
    res => console.log(res,"then3"),
    err => console.log(err)
)
// 结果
执行 then1

所以手写代码又有问题了,来看看是哪里问题。 通过大断点发现,有三个then,三个then都去执行了,但是resolve,却只执行了第一个,所以只有第一个then有结果,所以我们得让每个resolve都执行。会想到,因为我们的then任务是存起来的,存到了callbacks里面。但是resolve却没有执行,那我们把每个then的resolve也存到callbacks里面,不久可以调用了吗?所以我们将回调函数添加到 callbacks 数组中时候需要改造一下。得到下面代码:

js
class SelfPromise {
  constructor(){
  +
  +
  then(onFulfilled, onRejected) {
    return new SelfPromise((resolve, reject) => {
      onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
      onRejected = typeof onRejected === 'function' ? onRejected : () => {};
      if(this.PromiseState === SelfPromise.PADDIBNG){
        this.callbacks.push({
          + onFulfilled: (result) => {
          + try {
          +     // 如果没有传入成功回调函数,则将结果传递给下一个 MyPromise 对象
          +     resolve(
          +       typeof onFulfilled === "function"
          +           ? onFulfilled(result)
          +           : result
          +     );
          +   } catch (error) {
          +     // 如果执行成功回调函数出现错误,则将错误传递给下一个 MyPromise 对象
          +     reject(error);
          +   }
          + },
          + onRejected: (error) => {
          +   try {
          +     // 如果没有传入失败回调函数,则将错误传递给下一个 MyPromise 对象
          +     resolve(
          +         typeof onRejected === "function" ? onRejected(error) : error
          +       );
          +   } catch (error) {
          +     // 如果执行失败回调函数出现错误,则将错误传递给下一个 MyPromise 对象
          +     reject(error);
          +   }
          },
        })
      }
      if(this.PromiseState === SelfPromise.FULILLED){
        setTimeout(()=>{
          onFulfilled(this.PromiseResult)
        })
      }
      if(this.PromiseState === SelfPromise.REJECT){
        setTimeout(()=>{
          onRejected(this.PromiseResult)
        })
      }
    })
  }
  +
  +
}

再来执行手写Promise。

js
  const P = new SelfPromise((resolve,reject) => {
      resolve("执行");
  }).then( 
      res => console.log(res,"then1"),
      err => console.log(err)
  ).then( 
      res => console.log(res,"then2"),
      err => console.log(err)
  ).then( 
      res => console.log(res,"then3"),
      err => console.log(err)
  )
  // 结果
  执行 then1
undefined 'then2'
undefined 'then3'

到这里。手写Promise基础版本就完成啦。如果只是面对面试的话,你已经得了80分了,但是面试官可能让你写Promise的其他Api(race、all等),我们这先写好基础版本,接下来继续完善。

完整代码

js
class SelfPromise {
  static PADDIBNG = "等待";
  static FULILLED = "成功";
  static REJECT = "拒绝";
  constructor(executor) {
    // 存储 Promise 状态
    this.PromiseState = SelfPromise.PADDIBNG;
    // 存储 Promise 结果
    this.PromiseResult = null;
    // 存储 Promise 回调函数
    this.callbacks = [];
    this.resolve = (result) => {
      setTimeout(() => {
        if(this.PromiseState === SelfPromise.PADDIBNG){
          // 更新状态
          this.PromiseState = SelfPromise.FULILLED;
          // 存储结果
          this.PromiseResult = result;
          // 执行回调函数
          this.callbacks.forEach((callback) => callback.onFulfilled(result));
        }
      });
    };
    // 将 reject 函数绑定到 Promise 实例上
    this.reject = (error) => {
      setTimeout(() => {
        if(this.PromiseState === SelfPromise.PADDIBNG){
          // 更新状态
          this.PromiseState = SelfPromise.REJECT;
          // 存储结果
          this.PromiseResult = error;
          // 执行回调函数
          this.callbacks.forEach((callback) => callback.onRejected(result));
        }
      });
    };
    try {
        // 执行器函数接受 resolve 和 reject 函数作为参数
        executor(this.resolve, this.reject);
    } catch (error) {
        this.reject(error)
    }
  }
  then(onFulfilled, onRejected) {
    return new SelfPromise((resolve, reject) => {
      onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
      onRejected = typeof onRejected === 'function' ? onRejected : () => {};
      if(this.PromiseState === SelfPromise.PADDIBNG){
          this.callbacks.push({
              onFulfilled: (result) => {
                  try {
                      // 如果没有传入成功回调函数,则将结果传递给下一个 MyPromise 对象
                      resolve(
                          typeof onFulfilled === "function"
                              ? onFulfilled(result)
                              : result
                      );
                  } catch (error) {
                      // 如果执行成功回调函数出现错误,则将错误传递给下一个 MyPromise 对象
                      reject(error);
                  }
              },
              onRejected: (error) => {
                  try {
                      // 如果没有传入失败回调函数,则将错误传递给下一个 MyPromise 对象
                      resolve(
                          typeof onRejected === "function" ? onRejected(error) : error
                      );
                  } catch (error) {
                      // 如果执行失败回调函数出现错误,则将错误传递给下一个 MyPromise 对象
                      reject(error);
                  }
              },
          })
      }
      if(this.PromiseState === SelfPromise.FULILLED){
          setTimeout(()=>{
              onFulfilled(this.PromiseResult)
          })
      }
      if(this.PromiseState === SelfPromise.REJECT){
          setTimeout(()=>{
              onRejected(this.PromiseResult)
          })
      }
    })
  }
  catch(onRejected) {
  // 调用 then 方法,并将 onRejected 函数作为第二个参数传入
  return this.then(null, onRejected);
};
}

对于手写代码,如果没有写过的话,着实挺费劲,但是,当你看过几遍,手写几遍之后,你就会发现,这个太简单了吧,而且经常手写这些有些代码你会得到质的提升,所以要加油。所以还是那句话,没有牛逼的程序员,只有勤劳的程序员。

最后撒花 🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉

Last updated: