#yyds干货盘点#【Promise 源码学习】第五篇 - 实现 Promise 对异步操作的支持

theme: fancy 小知识,大挑战!本文正在参与“[程序员必备小知识](https://juejin.cn/post/7008476801634680869 "https://juejin.cn/post/7008476801634680869")”创作活动。 本文已参与「[掘力星计划](https://juejin.cn/post/7012210233804079141/ "https://juejin.cn/post/7012210233804079141/")」,赢取创作大礼包,挑战创作激励金。 一,前言 上一篇,翻译并理解了整个 Promise A+ 规范; 本篇开始,将基于 Promise A+ 规范,对我们的简版 Promise 源码进行功能完善; 本篇,将实现 Promise 对异步操作的支持; 二,前文回顾 在前面几篇中,结合对 Promise 基础功能的使用介绍和简单分析,手写了一个简版 Promise 源码,主要覆盖了以下几点: promise 是一个类; 使用 promise 时,传入 executor 执行器,并被立即执行; executor 参数是两个函数,用于描述 promise 实例的状态; resolve 表示成功,可以传入一个 value; reject 表示失败,可以传入一个 reason; 每个 Promise 实例都有一个 then 方法; promise 一旦状态发生后,不能再更改; promise 有三种状态:成功态,失败态,等待态(默认); 简版源码如下: const PENDING = 'PENDING'; // 等待态 const DULFILLED = 'DULFILLED'; // 成功态 const REJECTED = 'REJECTED'; // 失败态 class Promise{ // 通过 new Promise 进行实例化时,传入 executor 执行器函数 constructor(executor){ this.value = undefined; // 保存成功的原因,then中调用onFulfilled时传入 this.reason = undefined; // 保存失败的原因,then中调用onFulfilled时传入 this.state = PENDING; // promise 状态,默认等待态 // 成功 reslove 函数、失败reject函数,并传入executor const reslove = (value) =>{ // 等待态 --> 成功态 if(this.state === PENDING){ this.value = value this.state = DULFILLED; } } const reject = (reason) =>{ // 等待态 --> 失败态 if(this.state === PENDING){ this.reason = reason this.state = REJECTED; } } // 立即执行 executor 执行器函数,通过 try...catch... 进行异常捕捉; try{ executor(reslove, reject); }catch(e){ reject(e) // 有异常,调用 reject 更新为失败态 } } // 定义 then 方法:包含两个参数 onFulfilled 和 onRejected; // 根据 Promise 状态,执行 onFulfilled 或 onRejected; then(onFulfilled, onRejected){ // 成功态,调用 onFulfilled,传入成功 value if(this.state === DULFILLED){ onFulfilled(this.value) } // 失败态,执行 onRejected,传入失败 reason if(this.state === REJECTED){ onRejected(this.reason) } } } module.exports = Promise; 三,提出问题 前面说,Promise 的一个主要作用就是处理异步操作,使开发者使用同步编程方式处理异步操作,相比之前 callback 回调的处理方式,能够更好的解决/避免回调地狱的产生,同时还能实现控制权的反转; 1,测试原生 Promise 使用原生 Promise 执行异步操作: let promise = new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve('ok'); }, 1000) }) promise.then((value)=>{ console.log('success', value) },(reson)=>{ console.log('err',reson) }) // success o 2,测试手写 Promise // 引入手写的 promise.js let promise = new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve('ok'); }, 1000) }) promise.then((value)=>{ console.log('success', value) },(reson)=>{ console.log('err',reson) } 执行结果将不会输出任何内容,即 then 中的成功回调 onFulfilled 和失败回调 onRejected 都没有被执行; 3,问题分析 执行过程分析: 当 new Promise 完成后,executor 执行器函数被立即执行,定时器被启动; promise.then 被执行,当前 promise 实例状态为 pending 态,不执行任何操作; 1 秒后定义器回调执行,调用 resolve,将当前 promise 实例状态更新为成功态; 问题原因: 定时器 1 秒后才会调用 reslove 函数,而此时 then 方法已经执行完毕; 所以,当前 promise 源码尚不支持异步操作,需要实现对异步操作的支持; 4,解决方案 使用队列先将 then 方法中的回调函数收集起来; 待 resolve 或 reject 被调用状态更新后,再执行对应的回调函数即可; 这种“先收集,再执行”的功能特征,符合订阅发布模式; 四,实现 Promise 对异步操作的支持 1,事件订阅:收集回调函数 当 Promise 执行异步操作时,状态为 PENDING; 此时,需要两个队列(数组)对成功/失败回调分别进行收集; class Promise{ constructor(executor){ this.state = PENDING; this.value = undefined; this.reason = undefined; this.onResolvedCallbacks = []; // 收集成功回调 this.onRejectedCallbacks = []; // 收集失败回调 // ... } then(onFulfilled, onRejected){ // 执行异步操作时,收集成功/失败回调 if(this.state === PENDING){ this.onResolvedCallbacks.push(()=>{ onFulfilled(this.value) // 传入 value }) this.onRejectedCallbacks.push(()=>{ onRejected(this.value) // 传入 value }) } // ... } 这样,就完成了成功/失败回调函数的事件订阅操作; 2,事件发布:根据状态执行回调处理 当 Promise 中的 resolve 或 reject 函数被调用时,根据状态执行对应的回调处理: class Promise{ constructor(executor){ this.state = PENDING; this.value = undefined; this.reason = undefined; this.onResolvedCallbacks = []; this.onRejectedCallbacks = []; const reslove = (value) =>{ if(this.state === PENDING){ this.value = value this.state = DULFILLED; // 事件发布操作 this.onResolvedCallbacks.forEach(fn=>fn()) } } const reject = (reason) =>{ if(this.state === PENDING){ this.reason = reason this.state = REJECTED; // 事件发布操作 this.onRejectedCallbacks.forEach(fn=>fn()) } } // ... } // ... 这里相当于“订阅发布模式”中的事件发布; 3,测试对异步操作的支持 let promise = new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve('ok'); }, 1000) }) promise.then((value)=>{ console.log('success', value) },(reson)=>{ console.log('err',reson) }) // success o 五,结尾 本篇,主要实现了 Promise 对异步操作的支持,主要涉及以下几个点: 测试 Promise 对异步操作的支持; 分析当前 Promise 代码问题及解决方案; 使用发布订阅思想实现对异步操作的支持; Promise 异步操作的测试; 下一篇,实现 Promise 的链式调用;

提供优质的网站源码大全,小程序、APP、H5、支付、游戏、区块链、商城、直播、影音、小说、公众号等源码下载。
易搜网络技术公司 » #yyds干货盘点#【Promise 源码学习】第五篇 - 实现 Promise 对异步操作的支持
赞助VIP 享更多特权,建议使用 QQ 登录
喜欢我嘛?喜欢就按“ctrl+D”收藏我吧!♡