promise 的实现原理
class Pro {
constructor(a) {
this.code = "padding"
this.value = null
this.error = null
let res = (value) => {
if (this.code == "padding") {
setTimeout(() => { //宏函数 让他再最后执行
console.log("res被调用", this.code)
this.value = value
this.code = "fulfilled"
this.onfulfilled(this.value)
}, 0)
}
}
let err = (error) => {
if (this.code == "padding") {
setTimeout(() => {
console.log("err被调用", this.code)
this.error = error
this.code = "fulfilled"
}, 0)
}
}
a(res, err)
}
onthen(onfulfilled, onrejected) {
this.onfulfilled = onfulfilled
this.onrejected = onrejected
}
}
let m = new Pro((a, b) => {
a([1,2,3,4])
})
m.onthen(val=>{console.log(val,"...")},error=>{
console.log(error)
})
但是规范制作不希望使用宏任务,应该使用微任务 queueMicrotask
class Pro {
constructor(a) {
this.code = "padding"
this.value = null
this.error = null
let res = (value) => {
if (this.code == "padding") {
this.code = "fulfilled"
queueMicrotask(() => {
console.log("res被调用", this.code)
this.value = value
this.onfulfilled(this.value)
})
}
}
let err = (error) => {
if (this.code == "padding") {
this.code = "fulfilled"
queueMicrotask(() => {
console.log("err被调用", this.code)
this.error = error
this.onrejected(this.error)
})
}
}
a(res, err)
}
onthen(onfulfilled, onrejected) {
this.onfulfilled = onfulfilled
this.onrejected = onrejected
}
}
let m = new Pro((a, b) => {
setTimeout(()=>{
a([1,2,3,4])
},1000)
})
m.onthen(val=>{console.log(val,"...")},error=>{
console.log(error)
})
优化1 支持then的多次调用
class Pro {
constructor(a) {
this.code = "padding"
this.value = null
this.error = null
this.oklist=[]
this.errlist=[]
let res = (value) => {
if (this.code == "padding") {
queueMicrotask(() => {
this.code = "fulfilled"
console.log("res被调用", this.code)
this.value = value
this.oklist.forEach(val=>{
val(this.value) //微任务执行的then
})
})
}
}
let err = (error) => {
if (this.code == "padding") {
queueMicrotask(() => {
this.code = "fulfilled"
console.log("err被调用", this.code)
this.error = error
this.errlist.forEach(val=>{
val(this.value)
})
})
}
}
a(res, err)
}
onthen(onfulfilled, onrejected) {
this.oklist.push(onfulfilled)
if(this.code=="fulfilled"){ //支持settimeout的异步调用then的操作
onfulfilled(this.value)
}
this.errlist.push(onrejected)
if(this.code=="fulfilled"){ //支持settimeout的异步调用then的操作
onrejected(this.value)
}
}
}
let m = new Pro((a, b) => {
a([1,2,3,4])
})
m.onthen(val=>{console.log(val,"...")},error=>{
console.log(error)
})
m.onthen(val=>{console.log(val,".11..")},error=>{
console.log(error)
})
setTimeout(()=>{
m.onthen(val=>console.log(val,"22"),error=>{
console.log(error)
})
console.log(1)
},1000)
问题:失败和成功会同时执行 优化then的链式结构
class PromiseA {
constructor(x) {
this.code = "dengdai"
this.val = null
this.err = null
this.valf = []
this.errf = []
let a = (val) => {
queueMicrotask(
() => {
this.code = "going"
this.val = val
this.valf.forEach(val => val())
})
}
let b = (err) => {
queueMicrotask(
() => {
this.code = "going"
this.err = err
this.errf.forEach(err => err())
})
}
try {
x(a, b)
} catch (e) {
//TODO handle the exception
b(e)
}
}
then(val, err) {
return new PromiseA((a, b) => {
if (this.code == "dengdai") {
this.valf.push(() => {
try {
let vals = val(this.val)
a(vals)
} catch (e) {
//TODO handle the exception
err(e)
}
})
this.errf.push(() => {
try {
a(err(this.err))
} catch (e) {
err(e)
}
})
} else if (this.code == "going") {
if (this.val != null) {
try {
let e = this.val
a(val(e))
} catch (e) {
//TODO handle the exception
err(e)
}
} else {
try {
let e = this.err
a(err(e))
} catch (e) {
//TODO handle the exception
err(e)
}
}
}
})
}
}
catch
class PromiseA {
constructor(x) {
this.code = "dengdai"
this.val = null
this.err = null
this.valf = []
this.errf = []
let a = (val) => {
queueMicrotask(
() => {
this.code = "going"
this.val = val
this.valf.forEach(val => val())
})
}
let b = (err) => {
queueMicrotask(
() => {
this.code = "going"
this.err = err
this.errf.forEach(err => err())
})
}
try {
x(a, b)
} catch (e) {
//TODO handle the exception
b(e)
}
}
then(val, err) {
err=err||(err=>{throw err})
return new PromiseA((a, b) => {
if (this.code == "dengdai") {
if(val!=null){
this.valf.push(() => {
try {
let vals = val(this.val)
a(vals)
} catch (e) {
//TODO handle the exception
b(e)
}
})
}
if(err!=null){
this.errf.push(() => {
try {
let k = this.err
a(err(k))
} catch (e) {
b(e)
}
})
}
} else if (this.code == "going") {
if (this.val != null) {
try {
let e = this.val
a(val(e))
} catch (e) {
//TODO handle the exception
b(e)
}
} else {
try {
let e = this.err
a(err(e))
} catch (e) {
//TODO handle the exception
b(e)
}
}
}
})
}
catch(b){
this.then(undefined,b)
}
}
//添加finally方法
class PromiseA {
constructor(x) {
this.code = "dengdai"
this.val = null
this.err = null
this.valf = []
this.errf = []
let a = (val) => {
queueMicrotask(
() => {
this.code = "going"
this.val = val
this.valf.forEach(val => val())
})
}
let b = (err) => {
queueMicrotask(
() => {
this.code = "going"
this.err = err
this.errf.forEach(err => err())
})
}
try {
x(a, b)
} catch (e) {
//TODO handle the exception
b(e)
}
}
then(val, err) {
err=err||(err=>{throw err}) //让其为undefined时拿到值
val=val||(val=>val)//让其为undefined时拿到值
return new PromiseA((a, b) => {
if (this.code == "dengdai") {
if(val!=null){
this.valf.push(() => {
try {
let vals = val(this.val)
a(vals)
} catch (e) {
//TODO handle the exception
b(e)
}
})
}
if(err!=null){
this.errf.push(() => {
try {
let k = this.err
a(err(k))
} catch (e) {
b(e)
}
})
}
} else if (this.code == "going") {
if (this.val != null) {
try {
let e = this.val
a(val(e))
} catch (e) {
//TODO handle the exception
b(e)
}
} else {
try {
let e = this.err
a(err(e))
} catch (e) {
//TODO handle the exception
b(e)
}
}
}
})
}
catch(b){
return this.then(undefined,b)
}
finally(or){
return this.then(()=>{
or()
},()=>{
or()
})
}
}
let m = new PromiseA((res, err) => {
res(1123)
})
m.then(val=>val+"123").then(val=>{console.log(val);return val+"bbb"}).catch(val=>console.log("err",val)).then(()=>{
console.log("结束")
})
resolve/reject 创建一个普通promise 和 错误的promise
class PromiseA {
constructor(x) {
this.code = "dengdai"
this.val = null
this.err = null
this.valf = []
this.errf = []
let a = (val) => {
queueMicrotask(
() => {
this.code = "going"
this.val = val
this.valf.forEach(val => val())
})
}
let b = (err) => {
queueMicrotask(
() => {
this.code = "going"
this.err = err
this.errf.forEach(err => err())
})
}
try {
x(a, b)
} catch (e) {
//TODO handle the exception
b(e)
}
}
then(val, err) {
err=err||(err=>{throw err})
val=val||(val=>val)
return new PromiseA((a, b) => {
if (this.code == "dengdai") {
if(val!=null){
this.valf.push(() => {
try {
let vals = val(this.val)
a(vals)
} catch (e) {
//TODO handle the exception
b(e)
}
})
}
if(err!=null){
this.errf.push(() => {
try {
let k = this.err
a(err(k))
} catch (e) {
b(e)
}
})
}
} else if (this.code == "going") {
if (this.val != null) {
try {
let e = this.val
a(val(e))
} catch (e) {
//TODO handle the exception
b(e)
}
} else {
try {
let e = this.err
a(err(e))
} catch (e) {
//TODO handle the exception
b(e)
}
}
}
})
}
catch(b){
return this.then(undefined,b)
}
finally(or){
return this.then(()=>{
or()
},()=>{
or()
})
}
static resolve(obj){
return new PromiseA((a,b)=>{
a(obj)
})
}
static reject(str){
return new PromiseA((a,b)=>{
throw str
})
}
}
all,allSettled
class PromiseA {
constructor(x) {
this.code = "dengdai"
this.val = null
this.err = null
this.valf = []
this.errf = []
let a = (val) => {
queueMicrotask(
() => {
this.code = "going"
this.val = val
this.valf.forEach(val => val())
})
}
let b = (err) => {
queueMicrotask(
() => {
this.code = "going"
this.err = err
this.errf.forEach(err => err())
})
}
try {
x(a, b)
} catch (e) {
//TODO handle the exception
b(e)
}
}
then(val, err) {
err=err||(err=>{throw err})
val=val||(val=>val)
return new PromiseA((a, b) => {
if (this.code == "dengdai") {
if(val!=null){
this.valf.push(() => {
try {
let vals = val(this.val)
a(vals)
} catch (e) {
//TODO handle the exception
b(e)
}
})
}
if(err!=null){
this.errf.push(() => {
try {
let k = this.err
a(err(k))
} catch (e) {
b(e)
}
})
}
} else if (this.code == "going") {
if (this.val != null) {
try {
let e = this.val
a(val(e))
} catch (e) {
//TODO handle the exception
b(e)
}
} else {
try {
let e = this.err
a(err(e))
} catch (e) {
//TODO handle the exception
b(e)
}
}
}
})
}
catch(b){
return this.then(undefined,b)
}
finally(or){
return this.then(()=>{
or()
},()=>{
or()
})
}
static resolve(obj){
return new PromiseA((a,b)=>{
a(obj)
})
}
static reject(str){
return new PromiseA((a,b)=>{
throw str
})
}
static all(list){
return new PromiseA((a,b)=>{
let lists =[]
list.forEach(val=>val.then(val=>{
lists.push(val)
if(lists.length==list.length){
a(lists)
}
},err=>{
b(err)
}))
})
}
static allSettled(list){
return new PromiseA((a,b)=>{
let lists = []
list.forEach(val=>{
val.then(vals=>{
lists.push("code: 200 value:"+vals)
if(list.length==lists.length){
a(lists)
}
},err=>{
lists.push("code: 400 value:"+err)
if(list.length==lists.length){
a(lists)
}
})
})
})
}
}
let m = new PromiseA((res, err) => {
setTimeout(()=>{
res(11234)
},1000)
})
let m1 = new PromiseA((res, err) => {
setTimeout(()=>{
res(1123)
},2000)
})
let m2 = new PromiseA((res, err) => {
throw "errpss"
})
// m.then(val=>val+"123").then(val=>{console.log(val);return val+"bbb"}).catch(val=>console.log("err",val)).then(()=>{
// console.log("结束")
// })
// let k = PromiseA.reject("hellow word").then(val=>console.log(val),err=>console.log())
let k = PromiseA.allSettled([m,m2,m1]).then(val=>console.log(val))
竞速 race
static race(list){
return new PromiseA((a,b)=>{
list.forEach(val=>{
val.then(val=>{
a(val)
},err=>{
b(err)
})
})
})
}
any方法
static any(list) {
return new PromiseA((a, b) => {
let lists = []
let sb = []
list.forEach(val => {
val.then(val => {
if (lists.length == 0) {
a(val)
lists.push(1)
}
}, err => {
sb.push(err)
if (sb.length == list.length) {
b(new AggregateError(sb))
}
})
})
})
}
let k = PromiseA.any([m2, m2, m2]).then(val => console.log(val), err => console.log(err.errors))
调用