const PENDING = 'pengding';
const SUCCEED = 'fulfilled';
const FAILED = 'rejected';
function resolvePromise(promise2, x, resolve, reject) {
var called;
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if (typeof x === 'function' || (typeof x === 'object' && x != null)) {
try {
let then = x.then;
if (typeof then === 'function') {
if (called) return;
called = true;
then.call(x, y => {
resolvePromise(promise2, y, resolve, reject);
}, r => {
reject(r);
})
} else {
if (called) return;
called = true;
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
function isPromise(p) {
if (typeof p === 'function' || (typeof p === 'object' && p != null)) {
return typeof p.then === 'function'
}
return false;
}
class Promise {
constructor(excutor) {
this.state = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = value => {
if (value instanceof Promise) {
return value.then(resolve, reject);
}
if (this.state === PENDING) {
this.state = SUCCEED;
this.value = value;
this.onResolvedCallbacks.forEach(cb => cb());
}
}
const reject = reason => {
if (this.state === PENDING) {
this.state = FAILED;
this.reason = reason;
this.onRejectedCallbacks.forEach(cb => cb());
}
}
try {
excutor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : err => {
throw err
};
var promise2;
promise2 = new Promise((resolve, reject) => {
if (this.state === SUCCEED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
})
}
if (this.state === FAILED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
})
}
if (this.state === PENDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
})
})
}
})
return promise2;
}
catch (errCallback) {
return this.then(null, reject(errCallback));
}
static resolve(value){
return new Promise((resolve, reject) => {
resolve(value);
})
}
static reject(reason){
return new Promise((resolve, reject) => {
reject(reason);
})
}
static all(promises) {
return new Promise((resolve, reject) => {
let arr = [];
let i = 0;
const processData = (key, value) => {
arr[key] = value;
if (++i == promises.length) {
resolve(arr);
}
}
for (let i = 0; i < promises.length; i++) {
let current = promises[i];
if (isPromise(current)) {
current.then(y => {
processData(i, y)
}, reject);
} else {
processData(i, current);
}
}
})
}
static race(promises) {
for (let i = 0; i < promises.length; i++) {
let current = promises[i];
if (isPromise(current)) {
current.then(resolve, reject);
} else {
resolve(current);
}
}
}
static try(tryCallback) {
return new Promise((resolve, reject) => {
return Promise.resolve(tryCallback()).then(resolve, reject);
})
}
}
Promise.prototype.finally = (callback) => {
return this.then(data => {
return new Promise((resolve, reject) => {
return resolve(callback());
}).then(() => data);
}, err => {
return new Promise((resolve, reject) => {
return resolve(callback());
}).then(() => {
throw err
});
})
}
module.exports = Promise;
网友评论