ES5
function PromiseDemo(callback) {
this.PromiseState = "pending"
this.PromiseResult = undefined
this.callbackFn = []
const _resolve = function (value) {
if (this.PromiseState !== "pending") return
this.PromiseState = "fulfilled"
this.PromiseResult = value
this.callbackFn.forEach(item => {
item.onFulfilled()
})
}.bind(this)
const _reject = function (value) {
if (this.PromiseState !== "pending") return
this.PromiseState = "rejected"
this.PromiseResult = value
this.callbackFn.forEach(item => {
item.onRejected()
})
}.bind(this)
try {
callback(_resolve, _reject)
} catch (error) {
this.PromiseState = "rejected"
if (typeof (error) === 'object') {
this.PromiseResult = error.message
return
}
this.PromiseResult = error
}
}
Object.assign(PromiseDemo.prototype, {
then(onFulfilled, onRejected) {
if (!(onFulfilled instanceof Function)) {
onFulfilled = value => value
}
if (!(onRejected instanceof Function)) {
onRejected = reson => reson
}
return new PromiseDemo((resolve, reject) => {
const _common = function (cb) {
setTimeout(() => {
try {
const value = cb(this.PromiseResult)
if (value instanceof PromiseDemo) {
value.then((val => {
resolve(val)
}), reson => {
reject(reson)
})
} else {
resolve(value)
}
} catch (error) {
reject(error)
}
})
}
if (this.PromiseState === "fulfilled") {
_common.call(this, onFulfilled)
} else if (this.PromiseState === "rejected") {
_common.call(this, onRejected)
} else {
this.callbackFn.push({
onFulfilled: _common.bind(this, onFulfilled),
onRejected: _common.bind(this, onRejected)
})
}
})
},
catch(onRejected) {
return this.then(undefined, onRejected)
}
})
PromiseDemo.resolve = function (value) {
if (value instanceof PromiseDemo) {
return value
} else {
new PromiseDemo((resolve, reject) => {
resolve(value)
})
}
}
PromiseDemo.reject = function (value) {
return new PromiseDemo((resolve, reject) => {
reject(value)
})
}
PromiseDemo.all = function (array) {
let arr = new Array(array.length);
let i = 0
return new PromiseDemo((resolve, reject) => {
array.forEach((item, index) => {
if (item.PromiseState === "fulfilled") {
arr[index] = item.PromiseResult
i++
if (i === array.length) {
resolve(arr)
}
} else {
reject(item.PromiseResult)
}
})
})
}
PromiseDemo.race = function(array) {
return new PromiseDemo((resolve,reject)=>{
array.forEach(item=>{
if(item.PromiseState == "fulfilled"){
resolve(item.PromiseResult)
}else {
reject(item.PromiseResult)
}
})
})
}
ES6
class PromiseDemo {
constructor(cb) {
this.PromiseState = "pending"
this.PromiseResult = undefined
this.callbackFun = []
const _resolve = value => {
if (this.PromiseState !== "pending") return
this.PromiseState = "fulfilled"
this.PromiseResult = value
this.callbackFun.forEach((item)=>{
item.onFulfilled()
})
}
const _reject = value => {
if (this.PromiseState !== "pending") return
this.PromiseState = "rejected"
this.PromiseResult = value
this.callbackFun.forEach((item)=>{
item.onRejected()
})
}
try {
cb(_resolve, _reject)
} catch (error) {
this.PromiseState = "rejected"
this.PromiseResult = value
}
}
then(onFulfilled, onRejected) {
return new PromiseDemo((resolve, reject) => {
const _common = (cb)=>{
setTimeout(() => {
try {
let value = cb(this.PromiseResult)
if (value instanceof PromiseDemo) {
value.then((value) => {
resolve(value), reson => {
reject(reson)
}
})
} else {
resolve(value)
}
} catch (error) {
reject(error)
}
})
}
if (this.PromiseState === "fulfilled") {
_common(onFulfilled)
} else if (this.PromiseState === "rejected") {
_common(onRejected)
}else {
this.callbackFun.push({
onFulfilled:_common.bind(this,onFulfilled),
onRejected:_common.bind(this,onRejected)
})
}
})
}
catch(onRejected) {
return this.then(undefined, onRejected)
}
static resolve(){
if (value instanceof PromiseDemo) {
return value
} else {
new PromiseDemo((resolve, reject) => {
resolve(value)
})
}
}
static reject(){
return new PromiseDemo((resolve, reject) => {
reject(value)
})
}
static all(array) {
let arr = new Array(array.length);
let i = 0
return new PromiseDemo((resolve, reject) => {
array.forEach((item, index) => {
if (item.PromiseState === "fulfilled") {
arr[index] = item.PromiseResult
i++
if (i === array.length) {
resolve(arr)
}
} else {
reject(item.PromiseResult)
}
})
})
}
static race(array) {
return new PromiseDemo((resolve,reject)=>{
array.forEach(item=>{
if(item.PromiseState == "fulfilled"){
resolve(item.PromiseResult)
}else {
reject(item.PromiseResult)
}
})
})
}
}