Promise
手动实现简易版
js
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
function myPromise(fn) {
this.state = PENDING
this.value = null
this.resolveFuns = []
this.rejectFuns = []
const resolved = (v) => {
setTimeout(() => {
if (this.state === PENDING) {
this.state = RESOLVED
this.value = v
this.resolveFuns.forEach(fun => fun(this.value))
}
}, 0)
}
const rejected = (err) => {
setTimeout(() => {
if (this.state === PENDING) {
this.state = REJECTED
this.value = err
this.rejectFuns.forEach(fun => fun(this.value))
}
}, 0)
}
try {
fn(resolved, rejected)
} catch (err) {
rejected(err)
}
}
myPromise.prototype.then = function (resolveFun, rejectFun) {
resolveFun = typeof resolveFun === 'function' ? resolveFun : v => v
rejectFun = typeof rejectFun === 'function' ? rejectFun : err => {
throw err
}
if (this.state === PENDING) {
this.resolveFuns.push(resolveFun)
this.rejectFuns.push(rejectFun)
}
if (this.state === resolveFun) {
resolveFun(this.value)
}
if (this.state === rejectFun) {
rejectFun(this.value)
}
}
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
function myPromise(fn) {
this.state = PENDING
this.value = null
this.resolveFuns = []
this.rejectFuns = []
const resolved = (v) => {
setTimeout(() => {
if (this.state === PENDING) {
this.state = RESOLVED
this.value = v
this.resolveFuns.forEach(fun => fun(this.value))
}
}, 0)
}
const rejected = (err) => {
setTimeout(() => {
if (this.state === PENDING) {
this.state = REJECTED
this.value = err
this.rejectFuns.forEach(fun => fun(this.value))
}
}, 0)
}
try {
fn(resolved, rejected)
} catch (err) {
rejected(err)
}
}
myPromise.prototype.then = function (resolveFun, rejectFun) {
resolveFun = typeof resolveFun === 'function' ? resolveFun : v => v
rejectFun = typeof rejectFun === 'function' ? rejectFun : err => {
throw err
}
if (this.state === PENDING) {
this.resolveFuns.push(resolveFun)
this.rejectFuns.push(rejectFun)
}
if (this.state === resolveFun) {
resolveFun(this.value)
}
if (this.state === rejectFun) {
rejectFun(this.value)
}
}
使用示例
js
new myPromise((resolve, reject) => {
console.log('123') // 123
// resolve(666)
reject(777)
}).then(res => {
console.log('success:' + res) // 666
}, err => {
console.log('error:' + err) // 777
})
new myPromise((resolve, reject) => {
console.log('123') // 123
// resolve(666)
reject(777)
}).then(res => {
console.log('success:' + res) // 666
}, err => {
console.log('error:' + err) // 777
})
符合A+规范
js
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
function myPromise(fn) {
this.state = PENDING
this.value = null
this.resolveFuns = []
this.rejectFuns = []
const resolved = (v) => {
if (v instanceof myPromise) {
return v.then(resolved, rejected)
}
setTimeout(() => {
if (this.state === PENDING) {
this.state = RESOLVED
this.value = v
this.resolveFuns.forEach(fun => fun(this.value))
}
}, 0)
}
const rejected = (err) => {
setTimeout(() => {
if (this.state === PENDING) {
this.state = REJECTED
this.value = err
this.rejectFuns.forEach(fun => fun(this.value))
}
}, 0)
}
try {
fn(resolved, rejected)
} catch (err) {
rejected(err)
}
}
function resolutionProcedure(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Error'))
}
if (x instanceof MyPromise) {
x.then(function (value) {
resolutionProcedure(promise2, value, resolve, reject)
}, reject)
}
let called = false
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then
if (typeof then === 'function') {
then.call(
x,
y => {
if (called) return
called = true
resolutionProcedure(promise2, y, resolve, reject)
},
e => {
if (called) return
called = true
reject(e)
}
)
} else {
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else {
resolve(x)
}
}
myPromise.prototype.then = function (resolveFun, rejectFun) {
resolveFun = typeof resolveFun === 'function' ? resolveFun : v => v
rejectFun = typeof rejectFun === 'function' ? rejectFun : err => {
throw err
}
let that = this
if (this.state === PENDING) {
return (promise2 = new myPromise((resolve, reject) => {
that.resolveFuns.push(() => {
try {
const res = resolveFun(that.value)
resolutionProcedure(promise2, res, resolve, reject)
} catch (err) {
reject(err)
}
})
that.rejectFuns.push(() => {
try {
const res = rejectFun(that.value)
resolutionProcedure(promise2, res, resolve, reject)
} catch (err) {
reject(err)
}
})
}))
}
if (this.state === RESOLVED) {
return (promise2 = new myPromise((resolve, reject) => {
setTimeout(() => {
try {
const res = resolveFun(that.value)
resolutionProcedure(promise2, res, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
}))
}
if (this.state === REJECTED) {
return (promise2 = new myPromise((resolve, reject) => {
setTimeout(() => {
try {
const res = rejectFun(this.value);
resolutionProcedure(promise2, res, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
}))
}
}
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
function myPromise(fn) {
this.state = PENDING
this.value = null
this.resolveFuns = []
this.rejectFuns = []
const resolved = (v) => {
if (v instanceof myPromise) {
return v.then(resolved, rejected)
}
setTimeout(() => {
if (this.state === PENDING) {
this.state = RESOLVED
this.value = v
this.resolveFuns.forEach(fun => fun(this.value))
}
}, 0)
}
const rejected = (err) => {
setTimeout(() => {
if (this.state === PENDING) {
this.state = REJECTED
this.value = err
this.rejectFuns.forEach(fun => fun(this.value))
}
}, 0)
}
try {
fn(resolved, rejected)
} catch (err) {
rejected(err)
}
}
function resolutionProcedure(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Error'))
}
if (x instanceof MyPromise) {
x.then(function (value) {
resolutionProcedure(promise2, value, resolve, reject)
}, reject)
}
let called = false
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then
if (typeof then === 'function') {
then.call(
x,
y => {
if (called) return
called = true
resolutionProcedure(promise2, y, resolve, reject)
},
e => {
if (called) return
called = true
reject(e)
}
)
} else {
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else {
resolve(x)
}
}
myPromise.prototype.then = function (resolveFun, rejectFun) {
resolveFun = typeof resolveFun === 'function' ? resolveFun : v => v
rejectFun = typeof rejectFun === 'function' ? rejectFun : err => {
throw err
}
let that = this
if (this.state === PENDING) {
return (promise2 = new myPromise((resolve, reject) => {
that.resolveFuns.push(() => {
try {
const res = resolveFun(that.value)
resolutionProcedure(promise2, res, resolve, reject)
} catch (err) {
reject(err)
}
})
that.rejectFuns.push(() => {
try {
const res = rejectFun(that.value)
resolutionProcedure(promise2, res, resolve, reject)
} catch (err) {
reject(err)
}
})
}))
}
if (this.state === RESOLVED) {
return (promise2 = new myPromise((resolve, reject) => {
setTimeout(() => {
try {
const res = resolveFun(that.value)
resolutionProcedure(promise2, res, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
}))
}
if (this.state === REJECTED) {
return (promise2 = new myPromise((resolve, reject) => {
setTimeout(() => {
try {
const res = rejectFun(this.value);
resolutionProcedure(promise2, res, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
}))
}
}
使用示例
js
new myPromise((resolve, reject) => {
console.log('123')
resolve(666)
// reject(777)
}).then(res => {
console.log('success:' + res)
}, err => {
console.log('err:' + err)
})I
new myPromise((resolve, reject) => {
console.log('123')
resolve(666)
// reject(777)
}).then(res => {
console.log('success:' + res)
}, err => {
console.log('err:' + err)
})I