Promise源码
const PENDING = 'PENDING'
const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'
function resolvePromise(x, promise2, resolve, reject) {
if (x === promise2) {
console.log('======')
return reject(new TypeError('类型错误'))
}
let called = false
try {
if (typeof x === 'object' && x !== null) {
const then = x.then
if (typeof then === 'function') {
x.then(
x,
v => {
if (called) return
called = true
resolvePromise(v, promise2, resolve, reject)
},
r => {
if (called) return
called = true
reject(r)
}
)
} else {
if (called) return
called = true
resolve(x)
}
} else {
if (called) return
called = true
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
}
class Promise {
constructor(exectuor) {
try {
exectuor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
status = PENDING
value = null
reason = null
onFullFilledCallbacks = []
onRejectedCallbacks = []
static all(args) {
return new Promise((resolve, reject) => {
args.reduce((prev, curr, i, arr) => {
if (curr instanceof Promise) {
curr.then(
v => {
prev[i] = v
if (prev.length === arr.length) {
resolve(prev)
}
},
r => {
reject(r)
}
)
} else {
prev[i] = curr
}
return prev
}, [])
})
}
static resolve(v) {
if (v instanceof Promise) return v
return new Promise((resolve, reject) => resolve(v))
}
static reject(r) {
return new Promise((resolve, reject) => {
reject(r)
})
}
static allSettled(args) {
return new Promise((resolve, reject) => {
function addData(prev, index, value) {
prev[index] = value
if (prev.length === args.length) {
resolve(prev)
}
}
args.reduce((prev, curr, index, arr) => {
if (curr instanceof Promise) {
curr.then(
res => {
addData(prev, index, {
value: res,
status: 'fulfilled'
})
},
r => {
addData(prev, index, {
reason: r,
status: 'rejected'
})
}
)
} else {
addData(prev, index, {
reason: curr,
status: 'fulfilled'
})
}
})
})
}
static race(args) {
return new Promise((resolve, reject) => {
args.forEach(item => {
if (item instanceof Promise) {
item.then(
v => {
resolve(v)
},
r => {
reject(r)
}
)
} else {
resolve(item)
}
})
})
}
finally(cb) {
return this.then(
v => {
return Promise.resolve(cb()).then(() => v)
},
r => {
return Promise.resolve(cb()).then(() => {
throw r
})
}
)
}
resolve = v => {
if (this.status === PENDING) {
this.status = RESOLVED
this.value = v
console.log(this.onFullFilledCallbacks)
this.onFullFilledCallbacks.forEach(c => c())
}
}
reject = r => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = r
this.onRejectedCallbacks.forEach(c => c())
}
}
then(onFullFilled, onRejected) {
debugger
if (typeof onFullFilled !== 'function') onFullFilled = v => v
if (typeof onFullFilled !== 'function') {
onRejected = r => {
throw r
}
}
const promise2 = new Promise((resolve, reject) => {
if (this.status === RESOLVED) {
queueMicrotask(() => {
try {
const x = onFullFilled(this.value)
resolvePromise(x, promise2, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === REJECTED) {
queueMicrotask(() => {
try {
const x = onRejected(this.reason)
resolvePromise(x, promise2, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === PENDING) {
this.onFullFilledCallbacks.push(() => {
queueMicrotask(() => {
try {
const x = onFullFilled(this.value)
resolvePromise(x, promise2, resolve, reject)
} catch (e) {
reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
queueMicrotask(() => {
try {
const x = onRejected(this.reason)
resolvePromise(x, promise2, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
})
return promise2
}
}
Promise.deferred = function() {
var result = {}
result.promise = new Promise(function(resolve, reject) {
result.resolve = resolve
result.reject = reject
})
return result
}
module.exports = Promise
then源码
then(onFullFilled, onRejected) {
if (typeof onFullFilled !== 'function') onFullFilled = v => v
if (typeof onFullFilled !== 'function') {
onRejected = r => {
throw r
}
}
const promise2 = new Promise((resolve, reject) => {
if (this.status === RESOLVED) {
queueMicrotask(() => {
try {
const x = onFullFilled(this.value)
resolvePromise(x, promise2, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === REJECTED) {
queueMicrotask(() => {
try {
const x = onRejected(this.reason)
resolvePromise(x, promise2, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === PENDING) {
this.onFullFilledCallbacks.push(() => {
queueMicrotask(() => {
try {
const x = onFullFilled(this.value)
resolvePromise(x, promise2, resolve, reject)
} catch (e) {
reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
queueMicrotask(() => {
try {
const x = onRejected(this.reason)
resolvePromise(x, promise2, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
})
return promise2
}