Promise手写
Promise对象
js
const PENDING='PENDING',
FULFILLED='FULFILLED',
REJECTED='REJECTED'
class MyPromise {
constructor(executor) {
// 默认是等待态
this.status = PENDING //状态
this.value = undefined //成功返回值
this.reason = undefined //失败返回值
this.onFulfillCallbacks = [] //成功回调
this.onRejectedCallbacks = [] //失败回调
const resolve = (value) => {
// 只有状态为 PENDING 时才允许修改状态,因为promise状态不可逆
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value
// 发布
this.onFulfillCallbacks.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
// 发布
this.onRejectedCallbacks.forEach(fn => fn())
}
}
// executor 中抛出错误时也会执行 reject()
try {
// 立即执行
executor(resolve, reject)
} catch (e) {
//报错直接reject
reject(e)
}
}
}Promise.prototype.then
js
/**
* @description:
* then方法会用到一个发布订阅模式,处理 executor 中的异步代码.
* 如果resolve()的是一个Promise,会自动将这个promise执行,并且采用他的状态,如果成功会将成功的结果向下一层传递,
* 如果then方法中的成功或者失败 执行的时候发生错误 会走下一个then的失败的回调
* 如果then方法返回了一个失败的promise他会走外层then的失败的回调
* 1、(then中传递的函数)判断成功/失败函数的返回结果
* 2、 如果是 promise 则,采用它的结果
* 3、 如果不是promise 则,继续将结果传递下去
* @param {*} onFulfilled
* @param {*} onRejected
*/
// 同一个promise then 多次
then(onFulfilled,onRejected){
onFulfilled = typeof onFulfilled === 'function'? onFulfilled: value => value; //onFulfilled是方法说明还是promise对象,否则是常量
onRejected = typeof onRejected === 'function'? onRejected: reason =>{ throw reason } ; //同上
// 可以不停的调用then方法,返还了一个新的promise
// 异步的特点 等待当前主栈代码都执行后才执行
let promise2=new MyPromise((resolve, reject) => {
if(this.status===FULFILLED){
//异步执行结果
// 为什么要使用 setTimeout ? 如果不使用 setTimeout ,promise2 则会报错,涉及到代码的执行顺序问题,
// 需要先 new完后再将结果赋值给 promise2 可以去掉 setTimeout 打印一下 promise2 看看
// setTimeout作用: 为了保证 promise2 已经 new 完了
setTimeout(()=>{
// try catch 用于 捕获 onFulfilled 函数的异常,比如 在执行 onFulfilled 函数的时候抛错,
// 或者 onFulfilled 函数中 手动抛出错误
// constructor 中的 try catch 无法捕获这里异步代码的异常
try{
// 调用当前then方法的结果,来判断当前这个promise2 是成功还是失败
let x=onFulfilled(this.value)
// 这里的x是普通值还是promise
// 如果是一个promise呢?继续递归下去
// 判断 x 和 promise2 和 promise 的关系
resolvePromise(promise2,x,resolve, reject)
}catch (e) {
reject(e)
}
},0)
}
if(this.status===REJECTED){
setTimeout(()=>{
try{
let x=onRejected(this.reason)
resolvePromise(promise2,x,resolve, reject)
}catch (e) {
reject(e)
}
},0)
}
if(this.status===PENDING){
// 订阅
this.onFulfillCallbacks.push(()=>{
try{
let x=onFulfilled(this.value)
resolvePromise(promise2,x,resolve, reject)
}catch (e) {
reject(e)
}
})
this.onRejectedCallbacks.push(()=>{
try{
let x=onRejected(this.reason)
resolvePromise(promise2,x,resolve, reject)
}catch (e) {
reject(e)
}
})
}
})
return promise2
}Promise.prototype.catch
js
catch(errorBack){
return this.then(null,errorBack)
}Promise.prototype.finally
js
//finally 执行完finally中的回调函数并把数据传递到最后
finally(callback){
return this.then(value=>{
return MyPromise.resolve(callback()).then(()=>value)
},reason=>{
return MyPromise.reject(callback()).then(()=>{
throw new Error('Error')
})
})
}Promise.resolve
js
static resolve(value){
if (value instanceof Promise) return value;
if (value === null) return null;
// 判断如果是promise
if (typeof value === 'object' || typeof value === 'function') {
try {
// 判断是否有then方法
let then = value.then;
if (typeof then === 'function') {
return new MyPromise(then.call(value)); // 执行value方法
}
} catch (e) {
return new MyPromise( (resolve, reject) =>{
reject(e);
});
}
}
return new MyPromise( (resolve, reject) =>{
// if(isPromise(value)){
// value.then(resolve,reject)
// }else{
// resolve(value);
// }
resolve(value);
});
}Promise.reject
js
static reject(reason){
return new MyPromise((resolve,reject)=>{
reject(reason)
})
}Promise.all
js
//当所有promise对象都成功时,状态为成功,当有一个promise对象失败时,状态就为失败
static all(values){
return new MyPromise((resolve,reject)=> {
let resultArr = []
let orderIndex = 0;
if (!isIterable(values)) {
throw new TypeError(`${values} is not iterable (cannot read property Symbol(Symbol.iterator))`);
}
let len=values.length
if(len===0){
resolve([])
}
//获得所有成功的promise对象返回值
const processResultByKey = (value,index)=>{
resultArr[index] = value
orderIndex++
if(orderIndex === len){
resolve(resultArr)
}
}
values.forEach((value,i)=>{
if(isPromise(value)){
//成功返回成功状态,并返回所有promise对象返回值,否则为失败
value.then(value=>{
processResultByKey(value,i)
},reject)
}else {
processResultByKey(value,i)
}
})
})
}Promise.any
js
//当所有promise对象都失败时,状态为失败,否则为成功
static any(values){
return new MyPromise((resolve,reject)=>{
let count=0
let len=values.length
if(len===0){
resolve([])
}
if (!isIterable(values)) {
throw new TypeError(`${values} is not iterable (cannot read property Symbol(Symbol.iterator))`);
}
values.forEach((item,i)=>{
if(isPromise(item)){
item.then((resolve,reject)=>{
count++
if(count===values.length){
reject(new Error('All promises were rejected'))
}
})
}else{
resolve(item);
}
/*item.then(value=>{
resolve(value)
},reason=>{
count++
if(count===values.length){
reject(new Error('All promises were rejected'))
}
})*/
})
})
}Promise.race
js
//返回第一个promise对象的返回值
static race(values){
return new MyPromise((resolve,reject)=>{
if (!isIterable(values)) {
throw new TypeError(`${values} is not iterable (cannot read property Symbol(Symbol.iterator))`);
}
values.forEach(value=>{
if(isPromise(value)){
value.then(resolve,reject)
}else{
resolve(value);
}
})
})
}Promise.allSettled
js
//获得所有promise对象的返回值,无论成功还是失败
static allSettled(values){
return new MyPromise((resolve,reject)=>{
const result=[]
let count=0
if (!isIterable(values)) {
throw new TypeError(`${values} is not iterable (cannot read property Symbol(Symbol.iterator))`);
}
let len=values.length
if(len===0){
resolve([])
}
const addData=(status,value,i)=>{
count++
result[i]={
status,
value
}
if(count===len){
resolve(result)
}
}
values.forEach((item,i)=>{
if(isPromise(item)){
item.then(res=>{
addData('Fulfilled',res,i)
},reason=>{
addData('Rejected',reason,i)
})
}else {
addData('Fulfilled',item,i)
}
})
})
}循环迭代解析promise对象
js
function resolvePromise(promise,x,resolve,reject){
// 如果 promise2 和 x 相同,抛出错误
if(promise===x){
return reject(new TypeError(' Chaining cycle detected for promise #MyPromise'))
}
// 判断x的类型
// promise 有n种实现 都符合了这个规范 兼容别人的promise
// 严谨 🇬应该判断 别人的promise 如果失败了就不能在调用成功 如果成功了不能在调用失败
let called=false
// 怎么判断 x是不是一个promise 看他有没有then方法
if((typeof x==='object'&&x!==null)||typeof x==='function'){
try{
// 取then方法可能会出错,所以需要使用 trycatch
let then=x.then
if(typeof then==='function'){
// 如果 then 为 一个函数,我就认为他是一个promise
// 直接使用取好的then,而不是使用x.then,否则会在次取值,有可能第一次取值没有报错,第二次取值就报错了
then.call(x,y=>{
// 如果promise是成功的就把结果向下传,如果失败的就让下一个人也失败
if(called) return ; //防止多次调用成功和失败
called=true
// resolve(y)
// 为什么要使用 递归?
resolvePromise(promise,y,resolve,reject)
},(r)=>{
// 报错的时候就直接往下走,不用再担心 是不是 promise 了
if(called) return ;
called=true
reject(r)
})
}else{
// 说明 x 是一个普通对象,直接成功即可
resolve(x)
}
}catch (e) {
// 为了辨别这个promise 防止调用多次
if(called) return ;
called=true
reject(e)
}
}else{
// x是个常量
resolve(x)
}
}判断是否是Promise对象
js
//判断是否是Promise对象
function isPromise (x) {
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
let then = x.then;
//有then方法则算是promise
return typeof then === 'function';
}
return false;
}判断是否可迭代
js
function isIterable (value) {
return value !== null && value !== undefined && typeof value[Symbol.iterator] === 'function';
}Promise实现源码
js
const PENDING='PENDING',
FULFILLED='FULFILLED',
REJECTED='REJECTED'
function resolvePromise(promise,x,resolve,reject){
// 如果 promise2 和 x 相同,抛出错误
if(promise===x){
return reject(new TypeError(' Chaining cycle detected for promise #MyPromise'))
}
// 判断x的类型
// promise 有n种实现 都符合了这个规范 兼容别人的promise
// 严谨 🇬应该判断 别人的promise 如果失败了就不能在调用成功 如果成功了不能在调用失败
let called=false
// 怎么判断 x是不是一个promise 看他有没有then方法
if((typeof x==='object'&&x!==null)||typeof x==='function'){
try{
// 取then方法可能会出错,所以需要使用 trycatch
let then=x.then
if(typeof then==='function'){
// 如果 then 为 一个函数,我就认为他是一个promise
// 直接使用取好的then,而不是使用x.then,否则会在次取值,有可能第一次取值没有报错,第二次取值就报错了
then.call(x,y=>{
// 如果promise是成功的就把结果向下传,如果失败的就让下一个人也失败
if(called) return ; //防止多次调用成功和失败
called=true
// resolve(y)
// 为什么要使用 递归?
resolvePromise(promise,y,resolve,reject)
},(r)=>{
// 报错的时候就直接往下走,不用再担心 是不是 promise 了
if(called) return ;
called=true
reject(r)
})
}else{
// 说明 x 是一个普通对象,直接成功即可
resolve(x)
}
}catch (e) {
// 为了辨别这个promise 防止调用多次
if(called) return ;
called=true
reject(e)
}
}else{
// x是个常量
resolve(x)
}
}
class MyPromise{
constructor(executor) {
// 默认是等待态
this.status=PENDING //状态
this.value=undefined //成功返回值
this.reason=undefined //失败返回值
this.onFulfillCallbacks=[] //成功回调
this.onRejectedCallbacks=[] //失败回调
const resolve=(value)=>{
// 只有状态为 PENDING 时才允许修改状态,因为promise状态不可逆
if(this.status===PENDING){
this.status=FULFILLED
this.value=value
// 发布
this.onFulfillCallbacks.forEach(fn=>fn())
}
}
const reject=(reason)=>{
if(this.status===PENDING){
this.status=REJECTED
this.reason=reason
// 发布
this.onRejectedCallbacks.forEach(fn=>fn())
}
}
// executor 中抛出错误时也会执行 reject()
try{
// 立即执行
executor(resolve,reject)
}catch (e) {
//报错直接reject
reject(e)
}
}
/**
* @description:
* then方法会用到一个发布订阅模式,处理 executor 中的异步代码.
* 如果resolve()的是一个Promise,会自动将这个promise执行,并且采用他的状态,如果成功会将成功的结果向下一层传递,
* 如果then方法中的成功或者失败 执行的时候发生错误 会走下一个then的失败的回调
* 如果then方法返回了一个失败的promise他会走外层then的失败的回调
* 1、(then中传递的函数)判断成功/失败函数的返回结果
* 2、 如果是 promise 则,采用它的结果
* 3、 如果不是promise 则,继续将结果传递下去
* @param {*} onFulfilled
* @param {*} onRejected
*/
// 同一个promise then 多次
then(onFulfilled,onRejected){
onFulfilled = typeof onFulfilled === 'function'? onFulfilled: value => value; //onFulfilled是方法说明还是promise对象,否则是常量
onRejected = typeof onRejected === 'function'? onRejected: reason =>{ throw reason } ; //同上
// 可以不停的调用then方法,返还了一个新的promise
// 异步的特点 等待当前主栈代码都执行后才执行
let promise2=new MyPromise((resolve, reject) => {
if(this.status===FULFILLED){
//异步执行结果
// 为什么要使用 setTimeout ? 如果不使用 setTimeout ,promise2 则会报错,涉及到代码的执行顺序问题,
// 需要先 new完后再将结果赋值给 promise2 可以去掉 setTimeout 打印一下 promise2 看看
// setTimeout作用: 为了保证 promise2 已经 new 完了
setTimeout(()=>{
// try catch 用于 捕获 onFulfilled 函数的异常,比如 在执行 onFulfilled 函数的时候抛错,
// 或者 onFulfilled 函数中 手动抛出错误
// constructor 中的 try catch 无法捕获这里异步代码的异常
try{
// 调用当前then方法的结果,来判断当前这个promise2 是成功还是失败
let x=onFulfilled(this.value)
// 这里的x是普通值还是promise
// 如果是一个promise呢?继续递归下去
// 判断 x 和 promise2 和 promise 的关系
resolvePromise(promise2,x,resolve, reject)
}catch (e) {
reject(e)
}
},0)
}
if(this.status===REJECTED){
setTimeout(()=>{
try{
let x=onRejected(this.reason)
resolvePromise(promise2,x,resolve, reject)
}catch (e) {
reject(e)
}
},0)
}
if(this.status===PENDING){
// 订阅
this.onFulfillCallbacks.push(()=>{
try{
let x=onFulfilled(this.value)
resolvePromise(promise2,x,resolve, reject)
}catch (e) {
reject(e)
}
})
this.onRejectedCallbacks.push(()=>{
try{
let x=onRejected(this.reason)
resolvePromise(promise2,x,resolve, reject)
}catch (e) {
reject(e)
}
})
}
})
return promise2
}
catch(errorBack){
return this.then(null,errorBack)
}
//finally 执行完finally中的回调函数并把数据传递到最后
finally(callback){
return this.then(value=>{
return MyPromise.resolve(callback()).then(()=>value)
},reason=>{
return MyPromise.reject(callback()).then(()=>{
throw new Error('Error')
})
})
}
static resolve(value){
if (value instanceof Promise) return value;
if (value === null) return null;
// 判断如果是promise
if (typeof value === 'object' || typeof value === 'function') {
try {
// 判断是否有then方法
let then = value.then;
if (typeof then === 'function') {
return new MyPromise(then.call(value)); // 执行value方法
}
} catch (e) {
return new MyPromise( (resolve, reject) =>{
reject(e);
});
}
}
return new MyPromise( (resolve, reject) =>{
// if(isPromise(value)){
// value.then(resolve,reject)
// }else{
// resolve(value);
// }
resolve(value);
});
}
static reject(reason){
return new MyPromise((resolve,reject)=>{
reject(reason)
})
}
//当所有promise对象都成功时,状态为成功,当有一个promise对象失败时,状态就为失败
static all(values){
return new MyPromise((resolve,reject)=> {
let resultArr = []
let orderIndex = 0;
if (!isIterable(values)) {
throw new TypeError(`${values} is not iterable (cannot read property Symbol(Symbol.iterator))`);
}
let len=values.length
if(len===0){
resolve([])
}
//获得所有成功的promise对象返回值
const processResultByKey = (value,index)=>{
resultArr[index] = value
orderIndex++
if(orderIndex === len){
resolve(resultArr)
}
}
values.forEach((value,i)=>{
if(isPromise(value)){
//成功返回成功状态,并返回所有promise对象返回值,否则为失败
value.then(value=>{
processResultByKey(value,i)
},reject)
}else {
processResultByKey(value,i)
}
})
})
}
//当所有promise对象都失败时,状态为失败,否则为成功
static any(values){
return new MyPromise((resolve,reject)=>{
let count=0
let len=values.length
if(len===0){
resolve([])
}
if (!isIterable(values)) {
throw new TypeError(`${values} is not iterable (cannot read property Symbol(Symbol.iterator))`);
}
values.forEach((item,i)=>{
if(isPromise(item)){
item.then((resolve,reject)=>{
count++
if(count===values.length){
reject(new Error('All promises were rejected'))
}
})
}else{
resolve(item);
}
/*item.then(value=>{
resolve(value)
},reason=>{
count++
if(count===values.length){
reject(new Error('All promises were rejected'))
}
})*/
})
})
}
//返回第一个promise对象的返回值
static race(values){
return new MyPromise((resolve,reject)=>{
if (!isIterable(values)) {
throw new TypeError(`${values} is not iterable (cannot read property Symbol(Symbol.iterator))`);
}
values.forEach(value=>{
if(isPromise(value)){
value.then(resolve,reject)
}else{
resolve(value);
}
})
})
}
static deferred(){
const dfd={}
dfd.promise=new MyPromise((resolve,reject)=>{
dfd.resolve=resolve
dfd.reject=reject
})
return dfd
}
//获得所有promise对象的返回值,无论成功还是失败
static allSettled(values){
return new MyPromise((resolve,reject)=>{
const result=[]
let count=0
if (!isIterable(values)) {
throw new TypeError(`${values} is not iterable (cannot read property Symbol(Symbol.iterator))`);
}
let len=values.length
if(len===0){
resolve([])
}
const addData=(status,value,i)=>{
count++
result[i]={
status,
value
}
if(count===len){
resolve(result)
}
}
values.forEach((item,i)=>{
if(isPromise(item)){
item.then(res=>{
addData('Fulfilled',res,i)
},reason=>{
addData('Rejected',reason,i)
})
}else {
addData('Fulfilled',item,i)
}
})
})
}
}
//判断是否是Promise对象
function isPromise (x) {
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
let then = x.then;
//有then方法则算是promise
return typeof then === 'function';
}
return false;
}
function isIterable (value) {
return value !== null && value !== undefined && typeof value[Symbol.iterator] === 'function';
}示例
js
// promise 测试
const MyPromise=require('./NativeJs/Promise')
let promise=new MyPromise((resolve,reject)=>{ //executor执行器
resolve('promise1')
/* setTimeout(()=>{
resolve('success')
},2000)*/
});
let promise2=promise.then((value)=>{
console.log(value) //promise1
return new MyPromise((resolve,reject)=>{
setTimeout(()=>{
resolve(new MyPromise((resolve,reject)=>{
resolve(new MyPromise((resolve,reject)=>{
resolve(new MyPromise((resolve,reject)=>{
resolve('new Promise3')
}))
}))
}))
// resolve('new Promise')
},2000)
})
},(reason)=>{
return reason
})
promise2.then().then().then().then().then().then((res)=>{
console.log(res) //new Promise3
}).catch((error)=>{
console.log('Error:'+error)
})
const resolved = MyPromise.resolve(2);
resolved.then(val => {
console.log('resolved', val) //resolved 2
}).finally(res=>{
console.log('finally'+res) //finallyundefined
})
const rejected = MyPromise.reject(1);
rejected.catch(val => {
console.log('reject', val) //reject 1
}).finally(res=>{
console.log('finally'+res) //finallyundefined
})
const resolved = MyPromise.resolve(1);
const rejected = MyPromise.reject(-1);
const rejected1 = MyPromise.reject(-2);
const resolved1 = MyPromise.resolve(17);
const p = Promise.race([rejected,resolved,resolved1]); //err1 -1
const p = Promise.any([rejected,resolved,resolved1]); // result 1
const p = Promise.all([rejected,resolved,resolved1,rejected1]); //err1 -1
//result [{ status: 'Fulfilled', value: 1 },
// { status: 'Fulfilled', value: 17 },
// { status: 'Rejected', value: -1 }]
const p = MyPromise.allSettled([resolved,resolved1,rejected]);
p.then((result) => {
console.log('result', result)
}).catch(err => {
console.log('err1', err)
})
// const p =MyPromise.deferred()
// console.log(p)