基于PromiseA+规范实现一个promise
2024-09-06 20:51:03
实现如果下规范的promise
Aplus规范
1,promise是一个类:有三个状态 pending/等待态 fulfilled/成功态 rejected/失败态
2,promise默认执行器立即执行
3,Promise的实例都有一个then方法
4,执行器中用户可以自己决定成功或者失败,并且传入成功或者失败的原因
5,如果excutor执行器函数发生异常的时候也会执行失败的逻辑
6,如果Promise一旦进入成功态就不能再变为失败态,反之亦然
// 定义promise三种状态
let PENDING = 'PENDING'
let RESOLVED = 'RESOLVED' // 成功状态
let REJECTED = 'REJECTED' // 失败状态
console.log('own') const resolvePromise = (promise2, x, resolve, reject) => {
// A+规范中 x和promise2引用同一个对象抛出类型错误
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
// 后续的条件要严格判断 保证代码能和别的库一起使用
// x可能是一个函数或者对象
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
try {
let then = x.then;
if (typeof then === 'function') {
// 只能判断then是函数就认为其是promise
then.call(x, y => {
resolve(y)
}, e => {
reject(e)
})
} else {
resolve(x)
}
} catch (e) {
//TODO handle the exception
} } else {
resolve(x)
}
} class Promise {
constructor(excutor) {
this.status = PENDING
// 成功和失败的原因需要保存
this.value = undefined; // 成功的值
this.reason = undefined; // 失败的值
this.onResolvedCallbacks = []; // 存储成功的回调函数数组
this.onRejectedCallbacks = []; // 存储失败的回调函数数组
// 只有等待态的时候才能更改状态 let resolve = (value) => { if(value instanceof Promise){
value.then(resolve,reject) // 判断是promise.resolve 中如果传promise 递归解析 ,有延迟效果
} if (this.status = PENDING) {
this.value = value;
this.status = RESOLVED;
this.onResolvedCallbacks.forEach(fn => fn())
} }
let reject = (reason) => {
if (this.status = PENDING) {
this.reason = reason;
this.status = REJECTED;
this.onRejectedCallbacks.forEach(fn => fn())
}
}
// 当函数发生异常直接抛出错误
try {
excutor(resolve, reject)
} catch (e) {
reject(e)
}
}
// 关于then方法:
// 1: promise 成功或者失败会传递到外层的下一个then方法
// 2: 返回的是普通值(除了promise之外的值)都会触底到下一then的成功中;出错的情况走到下一次的失败中;
// 3: 错误处理 。自己最近的then没有错误处理,会向下传递错误直到有错误处理
// 4: 每次执行完then 返回都是新的promise (一旦成功或者失败就不能够修改状态)
then (onFulfilled, onRejected) { // 如果then中返回一个promise 我需要用x来决定是决定promise返回成功还是失败 let promise2 = new Promise((resolve, reject) => { // 链式调用
if (this.status === RESOLVED) {
setTimeout(() => { // 为了让resolvePromise拿到promise2
try {
// 如果状态是成功了,需要调用传入的第一个onFulfilled函数
let x = onFulfilled(this.value) //成功的回调直接执行;执行完成后拿到结果;ps: 成功之后返回的直接执行拿到结果存放到x中
// 但是返回的promise 还能继续then,继续传递成功的结果
// x可能是promise,解析promise ,使用这个返回的结果决定下一个then是成功还是失败
resolvePromise(promise2, x, resolve, reject) // 调用了下一个promise的resolve
} catch (error) {
reject(error)
} }, 0)
}
if (this.status === REJECTED) {
setTimeout(() => { // 为了让resolvePromise拿到promise2
try {
// 如果状态失败了,就需要使用第二个函数讲失败的原因返回
let x = onRejected(this.reason)
// 处理失败
resolvePromise(promise2, x, resolve, reject) //普通值都会传递到下一个的成功
} catch (error) {
reject(error)
} }, 0)
}
// 调用then的时候可能是pending状态
if (this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
// todo
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0) })
this.onRejectedCallbacks.push(() => {
// todo
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error)
}
}, 0)
})
}
})
return promise2;
}
catch(errCallBack){
return this.then(null,errCallBack)
}
static resolve(data){
// 快速创建一个成功的promise
return new Promise((resolve,reject) => {
resolve(data)
})
}
static reject(reason){
// 快速创建一个失败的promise
return new Promise((resolve,reject) => {
reject(reason)
})
}
}
最新文章
- TODO:字节的那点事Go篇
- 带你走近AngularJS - 基本功能介绍
- 项目管理知识框架PMBOK(文字版)
- P264练习题1.2题
- ANT编译build.xml
- 亲测 asp.net 调用 webservice返回json
- IOS ScrollowView 滑动到边缘后不允许再拖动
- mysql允许远程IP访问
- 8.Spark SQL
- 改变UITableView选中行高亮的颜色
- JHipster简介
- Polar Code(1)关于Polar Code
- 开始Dev之路
- 《Linux内核设计与实现》读书笔记 3
- 用Synoptic Panel自定义基于图形的可视化控件--制作一张剧场售票统计报表
- [转]jquery设置select选中,赋值等操作
- U811.1接口EAI系列之三--采购订单生成--VB语言
- Apache POI – Reading and Writing Excel file in Java
- SSIS教程:创建简单的ETL包 -- 1. 创建项目和基本包
- 【BZOJ1564】【NOI2009】二叉查找树(动态规划)
热门文章
- .net为程序集签名之.pfx文件
- 网络编程 并发socketserver
- 海量数据分析更快、更稳、更准。GaussDB(for MySQL) HTAP只读分析特性详解
- sqlmap的使用手册
- luoguP6624 [省选联考 2020 A 卷] 作业题(莫比乌斯反演,矩阵树定理)
- 【Python 第1课】安装
- String--int互转
- 比较HQL、Criteria、Native-SQL这三者做查询的区别,以及应该如何进行选择?
- 在Spring框架中如何更有效地使用JDBC?
- MybatisPlus 多租户的常见问题