function resolvePromise(promise2,x,resolve,reject){
if(promise2 === x){
return reject(new TypeError('循环引用'));
};
if(x !=null && (typeof x === 'object' || typeof x === 'function')){
let called;
try{
let then = x.then;
if(typeof then === 'function'){
then.call(x,y => {
if(called) return;
called = true;
resolvePromise(promise2,y,resolve,reject)
},r => {
if(called) return;
called = true;
reject(r);
});
}else{
resolve(x);
}
}catch (e){
if(called) return;
called = true;
reject(e)
}
}else{
resolve(x)
}
}
class Promise {
constructor (executor){
this.status = 'panding';
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = (data) => {
if(this.status === 'pending'){
this.value = data;
this.status = "resolved";
this.onResolvedCallbacks.forEach(fn => fn());
}
}
let reject = (reason) => {
if(this.status === 'pending'){
this.reason = reason;
this.status = 'rejected';
this.onRejectedCallbacks.forEach(fn => fn());
}
}
try{
executor(resolve,reject);
}catch (e){
reject(e);
}
}
then(onFuiFilled,onRejected){
onFuiFilled = typeof onFuiFilled === 'function' ? onFuiFilled : y => y;
onRejected = typeof onRejected === 'function' ? onRejected :err => {throw err;}
let promise2;
if(this.status === 'resolved'){
promise2 = new Promise((resolve,reject) => {
setTimeout(() => {
try{
let x = onFuiFilled(this.value);
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e);
}
},0)
});
}
if(this.status === 'rejected'){
promise2 = new Promise((resolve,reject) => {
setTimeout(() => {
try{
let x = onRejected(this.reason);
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e);
}
},0)
});
}
if(this.status === 'pending'){
promise2 = new Promise((resolve,reject) => {
this.onResolvedCallbacks.push( () =>{
setTimeout(() => {
try{
let x = onFuiFilled(this.value);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
},0)
});
this.onRejectedCallbacks.push( ()=>{
setTimeout(() => {
try{
let x = onRejected(this.reason);
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
},0)
})
})
}
return promise2;
}
catch (onRejected) {
return this.then(null, onRejected);
}
}
Promise.all = function (promises) {
return new Promise(function (resolve, reject) {
let arr = [];
let i = 0;
function processData(index, data) {
arr[index] = data;
if (++i === promises.length) {
resolve(arr);
}
}
for (let i = 0; i < promises.length; i++) {
promises[i].then(function (data) {
processData(i, data)
}, reject)
}
})
}
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (var i = 0; i < promises.length; i++) {
promises[i].then(resolve,reject)
}
})
}
Promise.resolve = function(value){
return new Promise((resolve,reject) => resolve(value);
}
Promise.reject = function(reason){
return new Promise((resolve,reject) => reject(reason));
}
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise( (resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd
}
module.exports = Promise;