当前位置: 首页 > news >正文

手写Promise

构造器的实现

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'class MyPromise{#state = PENDING;#result = undefined;constructor(executor){const resolve = (data) => {this.#changeState(FULFILLED, data);};const reject = (reason) => {this.#changeState(REJECTED, reason);};try {executor(resolve, reject);} catch (err) {reject(err);}        }#changeState(state, result){if(this.#state !== PENDING) return;this.#state = state;this.#result = result;}
}
const p = new MyPromise((resolve, reject) =>{resolve(1);
});
  • Promise 的状态一旦定下来之后,在后续的所有过程中都不可能再去改变它的状态了
  • 如果再执行过程中报错,会执行rejected,但是捕获不到异步错误

Promise-then的回调执行时机

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'class MyPromise{#state = PENDING;#result = undefined;#handlers = [];constructor(executor){const resolve = (data) => {this.#changeState(FULFILLED, data);};const reject = (reason) => {this.#changeState(REJECTED, reason);};try {executor(resolve, reject);} catch (err) {reject(err);}        }#changeState(state, result){if(this.#state !== PENDING) return;this.#state = state;this.#result = result;this.#run();}#run(){if(this.#state === PENDING) return;while(this.#handlers.length){const {onFulfilled, onRejected, resolve, reject} = this.#handlers.shift();if(this.#state === FULFILLED){if(typeof onFulfilled === 'function'){onFulfilled(this.#result)}}else{if(typeof onRejected === 'function'){onRejected(this.#result)}}}}then(onFulfilled, onRejected){return new MyPromise((resolve, reject) =>{this.#handlers.push({onFulfilled,onRejected,resolve,reject,});this.#run();});}
}const p = new MyPromise((resolve, reject) =>{setTimeout(()=>{resolve(123);},1000)
});p.then((res) =>{console.log('promise 成功1', res);}, (err) =>{console.log('promise 失败1', err);}
);
p.then((res) =>{console.log('promise 成功2', res);}, (err) =>{console.log('promise 失败2', err);}
);
p.then((res) =>{console.log('promise 成功3', res);}, (err) =>{console.log('promise 失败3', err);}
);

为了判断什么时候调用,所以用一个handlers数组记录,并用run函数调用

Promise-then 的返回值

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'class MyPromise{#state = PENDING;#result = undefined;#handlers = [];constructor(executor){const resolve = (data) => {this.#changeState(FULFILLED, data);};const reject = (reason) => {this.#changeState(REJECTED, reason);};try {executor(resolve, reject);} catch (err) {reject(err);}        }#changeState(state, result){if(this.#state !== PENDING) return;this.#state = state;this.#result = result;this.#run();}// 判断一个函数是不是Promise(是否满足A+规范)#isPromiseLike(value){return value && typeof value.then === 'function' && (typeof value === 'object' || typeof value === 'function');}// 把一个函数放到微队列#runMicroTask(func){// node nextTickif(process && process.nextTick){process.nextTick(func);}// 浏览器 MutationObserverelse if(typeof MutationObserver === 'function'){const ob = new MutationObserver(fn);const text = document.createTextNode('1');ob.observe(text, { characterData: true});text.data = '2';}else{setTimeout(fn, 0);}}#runOne(callback, resolve, reject){this.#runMicroTask(()=>{if(typeof callback !== 'function'){const settled = this.#state === FULFILLED ? resolve : reject;settled(this.#result);return;}try {const data = callback(this.#result);if(this.#isPromiseLike(data)){data.then(resolve, reject);}else{resolve(data);}} catch (err) {reject(err);}});}#run(){if(this.#state === PENDING) return;while(this.#handlers.length){const {onFulfilled, onRejected, resolve, reject} = this.#handlers.shift();if(this.#state === FULFILLED){this.#runOne(onFulfilled, resolve, reject);}else{this.#runOne(onRejected, resolve, reject);}}}then(onFulfilled, onRejected){return new MyPromise((resolve, reject) =>{this.#handlers.push({onFulfilled,onRejected,resolve,reject,});this.#run();});}
}const p = new MyPromise((resolve, reject) =>{setTimeout(()=>{reject(123);},1000)
});p.then(null, (err) =>{console.log('promise 失败', err);return 456;}
).then((data) =>{console.log("ok",data);
});

这里有三种情况:

  • 对应的回调不是函数的情况
  • 回调是一个函数的情况
  • 返回结果是一个Promise的情况
http://www.lryc.cn/news/435763.html

相关文章:

  • 深度学习云服务器免费使用教程
  • 使用ansible的剧本制作salt-master与salt-minion的安装与启动服务过程
  • 数据库sqlite3
  • 开发基础之Python 函数(Basic Python Functions for Development)
  • Django_Vue3_ElementUI_Release_001_项目初始化
  • MySQL之安装与基础知识
  • 前端基础 | HTML基础:HTML结构,HTML常见标签
  • 宏任务和微任务+超全面试真题
  • 针对SVM算法初步研究
  • Java中的`String`不可变性详解
  • c# SMTP发送邮件
  • GPU基础 -- 并行化与阿姆达尔定律
  • Lua热更
  • 提升汽车行业软件质量:ASPICE培训的关键实践方法
  • 2024 全新智能识别 API 接口震撼登场
  • 《UniVS: Unified and Universal Video Segmentation with Prompts as Queries》要点提炼
  • 计算机毕业设计选题推荐-推拿知识互动平台-Java/Python项目实战
  • 基于SpringBoot+Vue+MySQL的瑜伽馆管理系统
  • 【MySQL】EXPLAIN(执行计划)关键字是什么?
  • Mybatis两种方式来调用sql语句
  • 第十八节:学习统一异常处理(自学Spring boot 3.x的第五天)
  • flink中slotSharingGroup() 的详解
  • ASPF 技术介绍
  • 77-java 装饰器模式和适配器模式区别
  • 5. Fabric 设置画布大小
  • 240912-通过Ollama实现网站知识总结
  • Debian 包管理工具apt使用
  • 如何模拟一个小程序项目打包的流程
  • 设计模式七大原则详解
  • Navicat On-Prem Server 2.0 | MySQL与MariaDB基础管理功能正式上云