1024到了,撸一个简化版Promise

基础内容

    所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
    Promise象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
    

基础功能实现

promise是一个对象

class MyPromise {
}

    
promise会接收一个执行器函数,这个函数会自动接收两个参数,一个resolve,一个rejected,他们分别代表异步操作成功执行和失败

class MyPromise {
  constructor(executor) {
    executor(this.resolve, this.rejected);
  }

  resolve = () => {

  }

  rejected = () => {

  }
}

    
promise有三种状态,状态在resolve以及rejected时发生改变,状态发生改变后executor就不会再往下执行

class MyPromise {
  status = 'pending';	// 新增
  constructor(executor) {
    executor(this.resolve, this.rejected);
  }

  resolve = () => {
    if (this.status !== 'pending') return;	// 新增
    this.status = 'fulfilled';	// 新增
  }

  rejected = () => {
    if (this.status !== 'pending') return;	// 新增
    this.status = 'rejected';	// 新增
  }
}

    
promise有then方法,接收一个成功回调函数和一个失败回调函数作为参数,回调函数会在promise对象状态发生改变之后执行,回调函数会接收promise对象resolve或者rejected时传入的参数

class MyPromise {
  status = 'pending';

  constructor(executor) {
    executor(this.resolve, this.rejected);
  }

  resolve = (result) => {	// 修改
    if (this.status !== 'pending') return;
    this.status = 'fulfilled';
    this.successResult = result;	// 新增
  }

  rejected = (reason) => {	// 修改
    if (this.status !== 'pending') return;
    this.status = 'rejected';
    this.failReason = reason;	// 新增
  }

  // 新增then方法
  then = (successCallback, failCallback) => {
    if (this.status === 'fulfilled') {
      successCallback(this.successResult);
    } else if (this.status === 'rejected') {
      failCallback(this.failReason);
    }
  }
}

    
promise的基础功能看似完成了,但是如果我们这时候直接进行测试的话是有问题的

const testRequest = new MyPromise((resolve, rejected) => {
  setTimeout(() => {
    resolve('异步测试内容')
  }, 1000);
})
testRequest.then((res) => {
  console.log(res);
})
console.log('同步输出的内容')

//输出:同步输出的内容

异步内容没有输出。
这是因为 JavaScript 由上至下执行的时候,遇到 testRequest.then 的时候就直接执行了,而这时候 testRequest对象还没有 resolve,状态就还没发生变化,因此此时 this.status 是 pending,既不是 fulfilled, 也不是 rejected,回调函数也就不会执行。所以要考虑让对象能够在状态发生改变后执行回调函数,也就是要在 resolve和 rejected 方法内执行回调

调整:

class MyPromise {
  status = 'pending';

  constructor(executor) {
    executor(this.resolve, this.rejected);
  }

  resolve = (result) => {
    if (this.status !== 'pending') return;
    this.status = 'fulfilled';
    this.successResult = result;
    // 新增
    if (this.successCallback) {
      this.successCallback(this.successResult);
    }
  }

  rejected = (reason) => {
    if (this.status !== 'pending') return;
    this.status = 'rejected';
    this.failReason = reason;
    // 新增
    if (this.failCallback) {
      this.failCallback(this.failReason);
    }
  }

  then = (successCallback, failCallback) => {
    if (this.status === 'fulfilled') {
      successCallback(this.successResult);
    } else if (this.status === 'rejected') {
      failCallback(this.failReason);
    } else {
      // 新增
      this.successCallback = successCallback;
      this.failCallback = failCallback;
    }
  }
}

再次进行测试:

const testRequest = new MyPromise((resolve, rejected) => {
  setTimeout(() => {
    resolve('测试内容')
  }, 1000);
})
testRequest.then((res) => {
  console.log(res);
})
console.log('同步输出的内容')

// 输出:
同步输出的内容
测试内容

    

promise的链式调用

其他内容就不写了,这里再写一下链式调用

new Promise(···).then(···).then(···).then(···)

    
在我们使用 Promise 时,当then中依旧返回了一个 Promise 对象时,就可以继续在后方调用 then 方法。回到我们自己写的 promise 中,要在 then 后面继续调用 then ,别的暂且不说,至少需要 then 方法中返回一个 Promise 对象,因此:

then = (successCallback, failCallback) => {
  const chainPromise = new MyPromise((resolve, rejected) => {	// 新增
    if (this.status === 'fulfilled') {
      successCallback(this.successResult);
    } else if (this.status === 'rejected') {
      failCallback(this.failReason);
    } else {
      this.successCallback = successCallback;
      this.failCallback = failCallback;
    }
  })
  return chainPromise;	// 新增
}

promise 的 then 方法中又返回了一个 promise ,可能有点绕,这时我们只需要注意几点
首先明确 MyPromise 的特性:

  1. promise的执行器在对象创建时就会立即执行

new MyPromise 创建时带入的函数会立即执行

  1. 有三个状态,只有在 resolve 和 rejected 时状态才会发生改变,只有状态发生改变了,才会去执行回调函数

不调用 resolve,rejected的话,then 就不会执行

然后明确:

  1. 回调函数执行后可能依旧返回一个 Promise 对象

successCallback执行后可能会得到一个Promise对象

  1. 除了第一个 then,后续的 then 都是返回的单独声明的 chainPromise 的方法

也就是说和我们在链式调用中的 then 中返回的promise没有直接的关系,是两个promise

首先,因为 promise 的执行器在对象创建时就会立即执行,因此可以得知我们这样改写对我们原来的功能并不会有影响(加不加promise,原来基础功能部分的那些内容都会立即执行)

然后,不执行 resolve,rejected 的话回调就不会执行,也就是除了第一个 then 以外的 then 都不会执行(因为 chainPromise 内没有执行 resolve 或 rejected ),因此我们需要寻找执行新的 promise 对象的 resolve 和 rejected 的时机

继续,successCallback执行后可能会得到一个Promise对象,那么我们肯定要接收并且进行判断的

class MyPromise {
  status = 'pending';

  constructor(executor) {
    executor(this.resolve, this.rejected);
  }

  resolve = (result) => {
    if (this.status !== 'pending') return;
    this.status = 'fulfilled';
    this.successResult = result;
    if (this.successCallback) {
      // 修改
      const result = this.successCallback(this.successResult);
      // 新增
      if (result instanceof MyPromise) {

      } else {
        
      }
    }
  }

  rejected = (reason) => {
    if (this.status !== 'pending') return;
    this.status = 'rejected';
    this.failReason = reason;
    if (this.failCallback) {
      this.failCallback(this.failReason);
    }
  }

  then = (successCallback, failCallback) => {
    const chainPromise = new MyPromise((resolve, rejected) => {
      if (this.status === 'fulfilled') {
        // 修改
        const result = successCallback(this.successResult);
        // 新增
        if (result instanceof MyPromise) {

        } else {

        }
      } else if (this.status === 'rejected') {
        failCallback(this.failReason);
      } else {
        this.successCallback = successCallback;
        this.failCallback = failCallback;
      }
    })
    return chainPromise;
  }
}

    
然后就简单了,执行 resolve 就行了,如果 result 是一个 promise 对象,我们就调用它的 then ,然后我们用 chainPromise 的 resovle 去接收一下就行了(上面说到的第二点,因为后续的 then 都是 chainPromise 的,不是 successCallback 返回的,因此必须用 chainPromise 的 resolve 去接收一下)

class MyPromise {
  status = 'pending';

  constructor(executor) {
    executor(this.resolve, this.rejected);
  }

  resolve = (result) => {
    if (this.status !== 'pending') return;
    this.status = 'fulfilled';
    this.successResult = result;
    if (this.successCallback) {
      const result = this.successCallback(this.successResult);
      if (result instanceof MyPromise) {
        result.then(res => this.chainResolve(res));	// 新增
      } else {
        this.chainResolve(result);	// 新增
      }
    }
  }

  rejected = (reason) => {
    if (this.status !== 'pending') return;
    this.status = 'rejected';
    this.failReason = reason;
    if (this.failCallback) {
      this.failCallback(this.failReason);
    }
  }

  then = (successCallback, failCallback) => {
    const chainPromise = new MyPromise((resolve, rejected) => {

      // 上面的resolve函数肯定不能直接拿到这里的resolve,用两个参数接一下
      this.chainResolve = resolve;	// 新增
      this.chainRejected = rejected;	// 新增
      
      if (this.status === 'fulfilled') {
        const result = successCallback(this.successResult);
        if (result instanceof MyPromise) {
          result.then(res => resolve(res));	// 新增
        } else {
          resolve(result);	// 新增
        }
      } else if (this.status === 'rejected') {
        failCallback(this.failReason);
      } else {
        this.successCallback = successCallback;
        this.failCallback = failCallback;
      }
    })
    return chainPromise;
  }
}

这里只写了 resolve 的内容,rejected同理
测试:

const testRequest = new MyPromise((resolve, rejected) => {
  setTimeout(() => {
    resolve('测试内容 1');
  }, 1000);
})
testRequest.then((res) => {
  console.log(res);
  return new MyPromise((resolve, rejected) => {
    setTimeout(() => {
      resolve('测试内容 2');
    }, 500);
  })
}).then(res => {
  console.log(res);
  return new MyPromise((resolve, rejected) => {
    setTimeout(() => {
      resolve('测试内容 3');
    }, 300);
  })
}).then(res => {
  console.log(res);
})

// 输出:
测试内容 1
测试内容 2
测试内容 3

收工,最后祝大家1024快乐,╰(°▽°)╯
加班不是福报,摸鱼才是王道!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值