手写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')
	}
)

在这里插入图片描述

好的,我可以帮您实现一个简单的 Promise。 首先,Promise 有三种状态:pending(等待中)、fulfilled(已成功)和 rejected(已失败)。 我们可以通过一个变量来表示当前的状态,例如: ```javascript const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; let status = PENDING; ``` 接下来,我们需要实现一个 Promise 构造函数,它接受一个函数作为参数,这个函数又接受两个参数,一个是 resolve 函数,一个是 reject 函数。这个函数在被调用时会执行一些异步操作,并在异步操作完成后调用 resolve 或 reject 函数来改变 Promise 的状态。 ```javascript function MyPromise(executor) { let status = PENDING; function resolve(value) { status = FULFILLED; // TODO: 处理 value } function reject(reason) { status = REJECTED; // TODO: 处理 reason } // 执行异步操作 executor(resolve, reject); } ``` 现在我们已经可以创建一个 Promise 了,但是它并没有什么用处。我们需要实现一个 then 方法,它接受两个参数,一个是成功时的回调函数,一个是失败时的回调函数。当 Promise 的状态为 fulfilled 时,调用成功回调函数,否则调用失败回调函数。如果 then 方法被重复调用,我们需要将回调函数保存起来,等到异步操作完成后再执行。 ```javascript function MyPromise(executor) { let status = PENDING; let onFulfilledCallbacks = []; let onRejectedCallbacks = []; function resolve(value) { status = FULFILLED; onFulfilledCallbacks.forEach(callback => callback(value)); } function reject(reason) { status = REJECTED; onRejectedCallbacks.forEach(callback => callback(reason)); } function then(onFulfilled, onRejected) { if (status === FULFILLED) { onFulfilled(value); } else if (status === REJECTED) { onRejected(reason); } else { onFulfilledCallbacks.push(onFulfilled); onRejectedCallbacks.push(onRejected); } } // 执行异步操作 executor(resolve, reject); return { then, }; } ``` 最后,我们需要实现 resolve 和 reject 方法,它们分别将 Promise 的状态改为 fulfilled 和 rejected,并将结果传递给 then 方法注册的回调函数。 ```javascript function MyPromise(executor) { let status = PENDING; let value; let reason; let onFulfilledCallbacks = []; let onRejectedCallbacks = []; function resolve(value) { status = FULFILLED; onFulfilledCallbacks.forEach(callback => callback(value)); } function reject(reason) { status = REJECTED; onRejectedCallbacks.forEach(callback => callback(reason)); } function then(onFulfilled, onRejected) { if (status === FULFILLED) { onFulfilled(value); } else if (status === REJECTED) { onRejected(reason); } else { onFulfilledCallbacks.push(onFulfilled); onRejectedCallbacks.push(onRejected); } } function MyPromise(resolve) { status = FULFILLED; value = resolve; onFulfilledCallbacks.forEach(callback => callback(value)); } function MyPromise(reject) { status = REJECTED; reason = reject; onRejectedCallbacks.forEach(callback => callback(reason)); } // 执行异步操作 executor(resolve, reject); return { then, resolve: MyPromise, reject: MyPromise, }; } ``` 现在我们已经实现了一个简单的 Promise,您可以使用它来处理异步操作了。需要注意的是,这个 Promise 只是一个简化版的实现,没有考虑到一些重要的细节,例如异步操作的异常情况、then 方法返回的是一个新的 Promise 等等。如果您需要在生产环境中使用 Promise,请使用原生的 Promise 或第三方库。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值