摘要:当的状态已经流转时,回调函数会立即被执行,当还处于状态时,回调函数被推入相应队列中等待执行。
概览
const PENDING = Symbol("PENDING"); const FULFILLED = Symbol("FULFILLED"); const REJECTED = Symbol("REJECTED"); class MyPromise { constructor(fn) {} then(successFn, failFn) {} catch(failFn) {} finally(finalFn){} static resolve(val) {} static reject(val) {} static all(promiseArr) {} static race(promiseArr) {} }
Promise 内部维护着三种状态 pending、fulfilled 和 rejected,状态只能从 pending 转变到 fulfilled,或从 pending 转变到 rejected 且该转变不可逆。
Promise 主要提供了三个实例方法 then,catch,finally,和4个静态方法 resolve,reject,all,race。所有方法都都返回一个Promise对象。
构造函数constructor(fn) { this.fulfilledQueue = []; this.rejectedQueue = []; this._status = PENDING; this._value = null; // 执行成功队列中的回调函数 const handleFulfilledQueue = () => { while(this.fulfilledQueue.length) { let fulfiledFn = this.fulfilledQueue.shift(); fulfiledFn(this._value); }; }; // 执行失败队列中的回调函数 const handleRejectedQueue = () => { while(this.rejectedQueue.length) { let rejectedFn = this.rejectedQueue.shift(); rejectedFn(this._value); }; }; // 完成状态转变,执行回调队列中的回调函数 const _resolve = (val) => { const fn = () => { if(this._status !== PENDING) { return; } if(val instanceof MyPromise) { val.then((res) => { this._status = FULFILLED; this._value = res; handleFulfilledQueue(); }, (err) => { this._status = REJECTED; this._value = err; handleRejectedQueue(); }); } else { this._status = FULFILLED; this._value = val; handleFulfilledQueue(); } } // 保证promise 回调函数一定是在同步任务之后执行; setTimeout(fn, 0); } // 完成状态Pending到REJECTED的转变,执行rejected队列中的回调函数 const _reject = (val) => { const fn = () => { if(this._status !== PENDING) { return; } this._status = REJECTED; this._value = val; handleRejectedQueue(); } setTimeout(fn, 0); } try { // 处理外部传入函数执行异常 fn(_resolve, _reject); } catch(e) { return _reject(e); } }
Promise 构造函数接收一个函数执行器作为参数,该执行器的两个参数 _resolve、_reject均为函数类型,由 Promise 内部实现。执行器在 Promise 构造函数中被立即执行。
注意: MyPromise 使用 Timeout 实现异步,使得 MyPromise 只能添加 macrotask,实际上原生的Promise 是 microtask
then 方法then(successFn, failFn) { return new MyPromise((resolve, reject) => { // 执行成功时的回调函数 const handleSucess = (fn) => { try { if(typeof fn === "function") { const res = fn(this._value); if(res instanceof MyPromise) { res.then(resolve, reject); } else { resolve(res); } } else { resolve(this._value) } } catch(e){ reject(e); } } // 执行失败时的回调函数 const handleFail = (fn) => { try { if(typeof fn === "function") { const res = fn(this._value); if(res instanceof MyPromise) { res.then(resolve, reject); } else { resolve(res); } } else { reject(this._value); } } catch(e) { reject(e); } } switch(this._status){ case PENDING: // 异步任务尚未完成,将回调函数推入相应队列 this.fulfilledQueue.push(() => { handleSucess(successFn); }); this.rejectedQueue.push(() => { handleFail(failFn); }); break; case FULFILLED: // 异步任务成功完成,执行成功回调函数 handleSucess(successFn); break; case REJECTED: // 异步任务已失败,执行失败回调函数 handleFail(failFn); break; default: console.log("Promise error status:", this._status); break; }; }); }
then 方法是 Promise 的一个主要方法,catch 和 finally 都可以用 then 来实现。当 Promise 的状态已经流转时,回调函数会立即被执行,当 Promise 还处于 Pending 状态时,回调函数被推入相应队列中等待执行。
完整代码class MyPromise { constructor(fn) { this.fulfilledQueue = []; this.rejectedQueue = []; this._status = PENDING; this._value = null; const handleFulfilledQueue = () => { while(this.fulfilledQueue.length) { let fulfiledFn = this.fulfilledQueue.shift(); fulfiledFn(this._value); }; }; const handleRejectedQueue = () => { console.log(this.rejectedQueue); while(this.rejectedQueue.length) { let rejectedFn = this.rejectedQueue.shift(); rejectedFn(this._value); }; }; // 完成状态转变,执行回调队列中的回调函数 const _resolve = (val) => { const fn = () => { if(this._status !== PENDING) { return; } if(val instanceof MyPromise) { val.then((res) => { this._status = FULFILLED; this._value = res; handleFulfilledQueue(); }, (err) => { this._status = REJECTED; this._value = err; handleRejectedQueue(); }); } else { this._status = FULFILLED; this._value = val; handleFulfilledQueue(); } } setTimeout(fn, 0); } // 完成状态Pending到REJECTED的转变,执行rejected队列中的回调函数 const _reject = (val) => { const fn = () => { if(this._status !== PENDING) { return; } this._status = REJECTED; this._value = val; handleRejectedQueue(); } setTimeout(fn, 0); } try { // 处理外部传入函数执行异常 fn(_resolve, _reject); } catch(e) { return _reject(e); } } then(successFn, failFn) { return new MyPromise((resolve, reject) => { // 执行成功时的回调函数 const handleSucess = (fn) => { try { if(typeof fn === "function") { const res = fn(this._value); if(res instanceof MyPromise) { res.then(resolve, reject); } else { resolve(res); } } else { resolve(this._value) } } catch(e){ reject(e); } } // 执行失败时的回调函数 const handleFail = (fn) => { try { if(typeof fn === "function") { const res = fn(this._value); if(res instanceof MyPromise) { res.then(resolve, reject); } else { resolve(res); } } else { reject(this._value); } } catch(e) { reject(e); } } switch(this._status){ case PENDING: // 异步任务尚未完成,将回调函数推入相应队列 this.fulfilledQueue.push(() => { handleSucess(successFn); }); this.rejectedQueue.push(() => { handleFail(failFn); }); break; case FULFILLED: // 异步任务成功完成,执行成功回调函数 handleSucess(successFn); break; case REJECTED: // 异步任务已失败,执行失败回调函数 handleFail(failFn); break; default: console.log("Promise error status:", this._status); break; }; }); } catch(failFn) { return this.then(null, failFn); } finally(finalFn){ return this.then(finalFn, finalFn); } static resolve(val) { if(val instanceof MyPromise) { return val; } else { return new MyPromise((resolve, reject) =>{ resolve(val); }); } } static reject(val) { return new MyPromise((resolve, reject) => { reject(val); }); } static all(promiseArr) { return new Promise((resolve, reject) =>{ const len = promiseArr.length; let count = 0; let result = []; for(let i = 0; i < len; i++) { promiseArr[i].then((val) => { count++; result.push[val]; if(count === len){ resolve(result); } }, (err) => { reject(err); }); } }); } static race(promiseArr) { return new Promise((resolve, reject) =>{ const len = promiseArr.length; for(let i = 0; i < len; i++) { promiseArr[i].then((val) => { resolve(val); }, (err) => { reject(err); }); } }); } }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/103251.html
摘要:从最开始的到封装后的都在试图解决异步编程过程中的问题。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。写一个符合规范并可配合使用的写一个符合规范并可配合使用的理解的工作原理采用回调函数来处理异步编程。 JavaScript怎么使用循环代替(异步)递归 问题描述 在开发过程中,遇到一个需求:在系统初始化时通过http获取一个第三方服务器端的列表,第三方服务器提供了一个接口,可通过...
摘要:从最开始的到封装后的都在试图解决异步编程过程中的问题。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。异步编程入门的全称是前端经典面试题从输入到页面加载发生了什么这是一篇开发的科普类文章,涉及到优化等多个方面。 TypeScript 入门教程 从 JavaScript 程序员的角度总结思考,循序渐进的理解 TypeScript。 网络基础知识之 HTTP 协议 详细介绍 HTT...
摘要:执行的时候呢即可如何处理链式的且保证顺序每个后面链一个对象该对象包含子三个属性当父状态改变完毕执行完相应的的时候呢,拿到子在等待这个子状态改变,在执行相应的。 promise源码分析 初级入门以及如何使用请看 阮一峰promise对象讲解 先上一坨代码,后面我们要基于这坨代码来实现自定义promise 原始方法 setTimeout(function(){ var a=100...
摘要:实现的一个简单的如果有错误的地方,希望大家能够不吝赐教仅实现及方法最下方有完整代码开始一个对象接收的是一个这个接收两个参数当我们在内执行或的时候,就会调用内定义的和函数然后,和函数会改变的状态所以它应该是像下面这样的保存值记录状态为,为,为 实现的一个简单的ES6 Promise(如果有错误的地方,希望大家能够不吝赐教) 仅实现Promise及.then方法最下方有完整代码 开始 一个...
摘要:主要逻辑本质上还是回调函数那一套。通过的判断完成异步和同步的区分。 主要逻辑: 本质上还是回调函数那一套。通过_subscribers的判断完成异步和同步的区分。通过 resolve,reject -> publish -> invokeCallback -> resolve,reject的递归和下一条then的parent是上一条的child来完成then链的流转 同步情况...
阅读 2452·2021-11-24 09:39
阅读 3496·2019-08-30 15:53
阅读 574·2019-08-29 15:15
阅读 2877·2019-08-26 13:23
阅读 3188·2019-08-26 10:48
阅读 615·2019-08-26 10:31
阅读 730·2019-08-26 10:30
阅读 2303·2019-08-23 18:32