手写Promise,实现then,finally, all, resolve,reject,allSettled功能

手写promise

这次的博客就是这么干,赋值粘贴就能运行。

前序

js底层的promise是用c写的, 这里只是用js写了个思路来实现。

promise脑图

在这里插入图片描述

使用守则和注意事项

  • 建议把代码复制到本地编辑器查看。
  • 创建一个html文档,在html文档里的script里面引入KPromise模块
  • 注意要把script的type=‘module’,并且需要在本地起服务打开,否则不能引入KPromise模块
  • 创建一个名为KPrimise.js的文件,把下面的js代码赋值粘贴。
    在这里插入图片描述

html文件

<script type='module'>
import KPromise from './KPromise'
const p1 = new KPromise((resolve, reject)=> 
	resolve('ok')
	// reject('err')
	).then(res => {
		console.log(res)
		}, err => {
		console.log(err)
	})
</script>

KPromise.js

export default class KPromise {
  constructor(handle) {
    this.state = "pending";
    this.result = undefined;
    this.resolveQueue = [];
    this.rejectQueue = [];
    handle(this._resolve.bind(this), this._reject.bind(this));
  }
  _resolve(val) {
    this.state = "fulfilled";
    this.result = val;
    // 异步执行then里面的语句,把run微任务异步执行
    const run = () => {
      let cb;
      while ((cb = this.resolveQueue.shift())) {
        cb && cb(val);
      }
    };

    let ob = new MutationObserver(run)
    ob.observe(document.body, {
        attributes: true
    })
    document.body.setAttribute('joy', 'joy')
  }
  _reject(err) {
    this.state = "rejected";
    this.result = err;
    // 异步执行then里面的语句
    const run = () => {
      let cb;
      while ((cb = this.rejectQueue.shift())) {
        cb && cb(err);
      }
    };
    let ob = new MutationObserver(run)
    ob.observe(document.body, {
        attributes: true
    })
    document.body.setAttribute('joy', 'joy')
  }
  // then返回的是promise实例
  // then 执行里面方法的时候可以改变其状态
  then(onResolved, onRejected) {
    return new KPromise((resolve, reject) => {
      // 把onResolved 存入 resolveFn队列
      let resolveFn = (val) => {
        let res = onResolved && onResolved(val);
        if (res instanceof KPromise) {
          // 如果是KPromise就递归
          res.then(resolve, reject);
        } else {
          resolve(res);
          // resolve方法的功能:
          // 1. 改变state为fulfilled
          // 2. 生成一个异步方法run,传入val
        }
      };
      let rejectFn = (err) => {
        let res = onRejected && onRejected(err);
        if (res instanceof KPromise) {
          res.then(resolve, reject);
        } else {
          resolve(res);
          // 如果返回的结果是undefined或者常量,state = fulfilled, result(res)
        }
      };
      this.resolveQueue.push(resolveFn);
      this.rejectQueue.push(rejectFn);
    });
  }
  finally(callBack){
      return this.then(callBack, callBack)
  }
  static resolve(val) {
    // 获取一个promise实例。如果返回的结果是Promise
    return new KPromise((res, rej) => {
      if (val instanceof KPromise) {
        val.then(res, rej);
      } else {
        res(val);
      }
    });
  }
  static reject(val) {
    return new KPromise((res, rej) => {
      if (val instanceof KPromise) {
        val.then(res, rej);
      } else {
        res(val);
      }
    });
  }
  static all(lists) {
      // 返回一个promise实例,因为后面需要then
    return new KPromise((resolve) => {
      let resArr = [];
      let num = 0;
      // 把resolve(val) 这个val push进resArr, num++ 如果num和lists.length相等,说明每个
      // 都是resolve,就把这个结果传给下一个promise
      lists.forEach((item) => {
        item.then((res) => {
          resArr.push(res);
          num++;
          if (num === lists.length) {
            console.log(resArr); // [11,22,33] 每一个resolve(val) 的val值
            // resolve(resArr);
            return resArr

          }
        });
      });
      
    });
  }
  static allSettled(lists) {
    let resArr = new Array(lists.length);
    let num = 0;
    return new KPromise((resolve, reject) => {
      lists.forEach((item, key) => {
        let obj = {};
        item.then(
          (res) => {
            // resolve下来的res传给obj['value']
            obj["status"] = "fulfilled";
            obj["value"] = res;
            resArr[key] = obj;
            num++;
            //抛出resArr,在下一个Promise的resolve的函数里获取这个resArr
            if (num === lists.length) {
              resolve(resArr);
            }
          },
          (err) => {
            obj["status"] = "rejected";
            obj["reson"] = err;
            resArr[key] = obj;
            num++;
            // 如果最后一个是rejected,也是传给下一个Promise的resolve的函数里,当then的时候,可以在resolve的函数里获取这个resArr
            if (num === lists.length) {
              resolve(resArr);
            }
          }
        );
      });
    });
  }
}

  • 该Promise还有一些bug还没有解决,就是当throw err的时候,会抛错,并且不会执行接下来的方法,包括finally
let p1 = new KPromise((resolve, reject) => {
    setTimeout(() => {
       //resolve(111)
   		 reject(222)
    }, 1000)
})
p1.then(res => {
    console.log(res)
    console.log('world')
}, err => {
    console.log(err)
    throw err 
}).then(res => {
	console.log('hello')
}, err => {
    console.log(err)
}).finally(() =>{
		console.log('finally')
	}
)

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值