function MyPromise(fn) {
this.promiseState = 'pending'
this.promiseResult = undefined
this.thenCallback = undefined
this.catchCallback = undefined
var _this = this
var resolve = function(resolveValue) {
if (_this.promiseState == 'pending') {
_this.promiseState = 'fulfilled'
_this.promiseResult = resolveValue
if (resolveValue instanceof MyPromise) {
resolveValue.then(function(res) {
if (_this.thenCallback) {
_this.thenCallback(res)
}
})
} else {
setTimeout(function() {
if (_this.thenCallback) {
_this.thenCallback(resolveValue)
}
})
}
}
}
var reject = function(rejectValue) {
if (_this.promiseState == 'pending') {
_this.promiseState = 'rejected'
_this.promiseResult = rejectValue
setTimeout(function() {
if (_this.catchCallback) {
_this.catchCallback(rejectValue)
} else if (_this.thenCallback) {
_this.thenCallback(rejectValue)
} else {
throw ('no catch found')
}
})
}
}
if (fn) {
fn(resolve, reject)
} else {
throw ('Promise resolver undefined is not a fucntion')
}
}
MyPromise.prototype.then = function(callback) {
var _this = this
return new MyPromise(function(resolve, reject) {
_this.thenCallback = function(value) {
if (_this.promiseState == 'rejected') {
reject(value)
} else {
var res = callback(value)
if (res instanceof MyPromise &&
res.promiseState == 'rejected') {
res.catch(function(errValue) {
reject(errValue)
})
} else {
resolve(res)
}
}
}
})
}
MyPromise.prototype.catch = function(callback) {
var _this = this
return new MyPromise(function(resolve, reject) {
_this.catchCallback = function(value) {
var res = callback(value)
resolve(res)
}
})
}
MyPromise.resolve = function(value) {
return new MyPromise(function(resolve, reject) {
resolve(value)
})
}
MyPromise.reject = function(value) {
return new MyPromise(function(resolve, reject) {
reject(value)
})
}
MyPromise.all = function(promiseArr) {
var resArr = []
var errValue = undefined
return new MyPromise(function(resolve, reject) {
promiseArr.forEach((promiseItem, index) => {
promiseItem.then(function(res) {
resArr[index] = res
let success = promiseArr.every(item => {
return item.promiseState == 'fulfilled'
})
if (success) {
resolve(resArr)
}
}).catch(function(err) {
reject(err)
})
})
})
}
MyPromise.race = function(promiseArr) {
var resArr = []
var errValue = undefined
return new MyPromise(function(resolve, reject) {
promiseArr.forEach((promiseItem, index) => {
promiseItem.then(function(res) {
resolve(res)
}).catch(function(err) {
reject(err)
})
})
})
}
function generatorFunctionRunner(fn) {
let generator = fn()
let step = generator.next()
function loop(stepArg, generator) {
let value = stepArg.value
if (value instanceof Promise || value instanceof MyPromise) {
value.then(function(promiseValue) {
if (stepArg.done == false) {
loop(generator.next(promiseValue), generator)
}
})
} else {
if (stepArg.done == false) {
loop(generator.next(stepArg.value), generator)
}
}
}
loop(step, generator)
}
function* test() {
var res1 = yield new MyPromise(function(resolve) {
setTimeout(function() {
resolve('第一秒运行')
}, 1000)
})
console.log(res1)
var res2 = yield new MyPromise(function(resolve) {
setTimeout(function() {
resolve('第二秒运行')
}, 1000)
})
console.log(res2)
var res3 = yield new MyPromise(function(resolve) {
setTimeout(function() {
resolve('第三秒运行')
}, 1000)
})
console.log(res3)
}
generatorFunctionRunner(test)
class Kpromise {
constructor(handle) {
this.status = "pending";
this.value = undefined;
this.resolveQueue = [];
this.rejectQueue = [];
handle(this._resolve.bind(this), this._reject.bind(this));
}
_resolve(val) {
this.status = "fulfilled";
this.value = val;
const run = () => {
let cb;
while (cb = this.resolveQueue.shift()) {
cb && cb(val);
}
}
let ob = new MutationObserver(run);
ob.observe(document.body, {
attributes: true
})
document.body.setAttribute("kkb", Math.random());
}
_reject(val) {
this.status = "rejected";
this.value = val;
const run = () => {
let cb;
while (cb = this.rejectQueue.shift()) {
cb && cb(val);
}
}
let ob = new MutationObserver(run);
ob.observe(document.body, {
attributes: true
})
document.body.setAttribute("kkb", Math.random());
}
then(onResolved, onRejected) {
return new Kpromise((resolve, reject) => {
this.resolveQueue.push(val => {
let res = onResolved && onResolved(val);
if (res instanceof Kpromise) {
return res.then(resolve);
}
resolve(res);
})
this.rejectQueue.push(val => {
onRejected && onRejected(val);
reject(val);
});
})
}
catch(onRejected) {
this.then(undefined, onRejected);
}
static resolve(val) {
return new Kpromise(resolve => {
resolve(val);
})
}
static reject(val) {
return new Kpromise((resolve, reject) => {
reject(val);
})
}
static all(lists) {
let arr = [];
return new Kpromise((resolve, reject) => {
lists.forEach(item => {
item.then(res => {
arr.push(res);
if (arr.length === lists.length) {
resolve(arr);
}
})
})
})
}
static race(lists) {
return new Kpromise((resolve, reject) => {
lists.forEach(item => {
item.then(res => {
resolve(res);
}, err => {
reject(err);
})
})
})
}
finally(cb){
return this.then(res=>{
cb();
},err=>{
cb();
})
}
}