function版
(
function(window) {
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
function Promise(executor) {
let callbacks = []
this.status = PENDING
this.value = null
try{
executor(this.resolve.bind(this), this.reject.bind(this))
}catch(error) {
reject(error)
}
}
function resolve(value) {
if(this.status == PENDING) {
try{
this.status = RESOLVED
this.value = value
setTimeout(() => {
this.callbacks.map(callback=> {
callback.onResolved(value)
})
})
}catch(error) {
reject(error)
}
}
}
function reject(value) {
if(this.status == PENDING) {
try{
this.status = REJECTED
this.value = value
setTimeout(() => {
this.callbacks.map(callback => {
callback.onRejected(value)
})
})
}catch(error) {
reject(error)
}
}
}
Promise.prototype.then = function(onResolved, onRejected) {
onResolved = typeof onResolved === 'function' ? onResolved : value => value
onRejected = typeof onRejected === 'function' ? onRejected : value => value
return new Promise((resolve, reject) => {
if(this.status == PENDING) {
this.callbacks.push({
onResolved: value => {
parse(onResolved(value), resolve, reject)
},
onRejected: value => {
parse(onRejected(value), resolve, reject)
}
})
}else if (this.status == RESOLVED) {
setTimeout(() => {
parse(onResolved(this.value), resolve, reject)
})
}else {
setTimeout(() => {
parse(onRejected(this.value), resolve, reject)
})
}
})
}
function parse(result, resolve, reject) {
try{
if(result instanceof Promise) {
result.then(resolve, reject)
}else {
resolve(result)
}
}catch(error) {
reject(error)
}
}
Promise.resolve = function(value) {
return new Promise((resolve, reject) => {
parse(value, resolve, reject)
})
}
Promise.reject = function(value) {
return new Promise((_, reject) => {
reject(value)
})
}
Promise.all = function(promises) {
let resolves = []
return new Promise((resolve, reject) => {
promises.forEach((promise, index) => {
promise.then(value => {
resolves.push(value)
if(resolves.length == promises.length) {
resolve(resolves)
}
}, reason => {
reject(reason)
})
})
})
}
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
promises.forEach(promsie => {
promise.then(value => {
resolve(value)
})
})
})
}
window.Promise = Promise
}
)(window)
class版
class Promise{
static PENDING = 'pending'
static RESOLVED = 'resolved'
static REJECTED = 'rejected'
constructor(executor) {
this.callbacks = []
this.status = Promise.PENDING
this.value = null
try{
executor(this.resolve.bind(this), this.reject.bind(this))
}catch(error) {
this.reject(error)
}
}
resolve(value) {
if(this.status == Promise.PENDING) {
try{
this.status = Promise.RESOLVED
this.value = value
setTimeout(() => {
this.callbacks.map(callback=> {
callback.onResolved(value)
})
}, 0)
}catch(error) {
reject(error)
}
}
}
reject(value) {
if(this.status == Promise.REJECTED) {
try{
this.status = Promise.REJECTED
this.value = value
setTimeout(() => {
this.callbacks.map(callback=> {
callback.onRejected(value)
})
}, 0)
}catch(error) {
this.reject(error)
}
}
}
then(onResolved, onRejected) {
if(typeof onResolved != 'fucntion') {
onResolved = value => value
}
if(typeof onRejected != 'function') {
onRejected = value => value
}
return new Promise((resolve, reject)=> {
if(this.status == Promise.PENDING) {
this.callbacks.push({
onResolved : value => {
this.parse(onResolved(value), resolve, reject)
},
onRejected: value => {
this.parse(onRejected(
value), resolve, reject)
}
})
}
if(this.status == Promise.RESOLVED) {
setTimeout(() => {
this.parse(onResolved(this.value), resolve, reject)
}, 0)
}
if(this.status == Promise.REJECTED) {
setTimeout(()=> {
this.parse(onRejected(this.value), resolve, reject)
}, 0)
}
})
}
parse(result, resolve, reject) {
try {
if(result instanceof Promise) {
result.then(resolve, reject)
}else {
resolve(result)
}
}catch(error) {
reject(error)
}
}
static resolve(value) {
return new Promise((resolve,reject) => {
if(value instanceof Promise) {
value.then(resolve, reject)
} else{
resolve(value)
}
})
}
static reject(value) {
return new Promise((_, reject) => {
reject(value)
})
}
static all(promises) {
let resolves = []
return new Promise((resolve, reject) => {
promises.forEach(promise => {
promise.then(value => {
resolves.push(value)
if(resolves.length == promises.length) {
resolve(resolves)
}
}, reason=> {
reject(reason)
})
})
})
}
static race(promises) {
return new Promise((resolve, reject) => {
promises.map(promise=> {
promise.then(value => {
resolve(value)
})
})
})
}
}