const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const isFunction = obj => typeof obj === 'function'
const isPromise = obj => obj instanceof Promise
function Promise(f) {
this.state = PENDING
this.result = null
this.callbacks = []
const onFulfilled = value => {
transition(this, FULFILLED, value)
}
const onRejected = reason => {
transition(this, REJECTED, reason)
}
const resolve = value => {
resolvePromise(this, value, onFulfilled, onRejected)
// onFulfilled(value)
}
const reject = reason => {
onRejected(reason)
}
try {
f(resolve, reject)
} catch (error) {
reject(error)
}
}
const resolvePromise = (promise, result, onFulfilled, onRejected) => {
if (promise === result) {
return onRejected(new TypeError("禁止套娃"))
}
if (isPromise(result)) {
return result.then(onFulfilled, onRejected)
}
onFulfilled(result)
}
const transition = (promise, state, result) => {
if (promise.state !== PENDING) {
return
}
promise.state = state
promise.result = result
setTimeout(() => {
clearCallbacks(promise.callbacks, state, result)
}, 0);
}
const clearCallbacks = (callbacks, state, result) => {
while (callbacks.length) {
handleCallback(callbacks.shift(), state, result)
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
try {
const callback = { onFulfilled, onRejected, resolve, reject }
if (this.state === PENDING) {
this.callbacks.push(callback)
} else {
setTimeout(() => {
handleCallback(callback, this.state, this.result)
}, 0);
}
} catch (error) {
reject(error)
}
})
}
const handleCallback = (callback, state, result) => {
const { onFulfilled, onRejected, resolve, reject } = callback
if (state === FULFILLED) {
isFunction(onFulfilled) ? resolve(onFulfilled(result)) : resolve(result)
} else if (state === REJECTED) {
isFunction(onRejected) ? resolve(onRejected(result)) : reject(result)
}
}
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected)
}
Promise.resolve = value => new Promise(resolve => resolve(value))
Promise.reject = reason => new Promise((_, reject) => reject(reason))
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('请传入数组'))
}
const res = []
let count = 0;
promises.forEach((p, index) => {
Promise.resolve(p).then(data => {
res[index] = data
count++
if (count === promises.length) {
resolve(res)
}
}).catch((err) => {
reject(err)
})
})
})
}
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
promises.forEach(p => {
p.then(data => {
resolve(data)
}).catch((err) => {
reject(err)
})
})
})
}
const p1 = new Promise((r) => {
setTimeout(() => {
r(1)
}, 100);
})
const p2 = new Promise((r) => {
setTimeout(() => {
r(2)
}, 300);
})
const p3 = new Promise((r) => {
setTimeout(() => {
r(3)
}, 200);
})
const p4 = new Promise((_, r) => {
setTimeout(() => {
r(4)
}, 10);
})
Promise.race([p1, p2, p3, p4]).then((res) => {
console.log(res);
}).catch(console.log)
console