// /**
// * 实现Promise几个步骤
// * 1. 设置三个状态:pending、rejected、fulfilled
// * 2. 设置执行函数executor、成功回调函数resolve、失败回调函数reject
// * 3. 缓存then函数执行值,等待状态改变
// *
// * 下面其实就是一种发布订阅模式
// * 收集依赖 => 触发通知 => 取出依赖执行
// */
const Pending = 'pending';
const Rejected = 'rejected';
const Fulfilled = 'fulfilled';
function resolvePromise(promise2, data, resolve, reject) {
if (data === promise2) {
return reject(new TypeError('Chaining cycle is Error'));
}
let called = false;
if ((typeof data === 'object' && data !== null) || typeof data === 'function') {
try{
let then = data.then;
if (typeof then === 'function') {
then.call(data, v => {
if (called)return;
called = true;
resolvePromise(promise2, v, resolve, reject);
}, r => {
if (called)return;
called = true;
// 注意这个地方,既然reject就不需要在执行resolvePromse,不再向下传递
reject(r);
});
} else {
resolve(data);
}
} catch(e){
if (called) return;
called = true;
reject(e);
}
} else {
console.log('resolvePromise', data);
// 普通值
resolve(data);
}
}
class Promise {
constructor(executor) {
this.status = Pending;
this.value = undefined;
this.reason = undefined;
this.resolveList = [];
this.rejectList = [];
let resolve = (value) => {
if (this.status === Pending) {
console.log(this.resolveList);
this.status = Fulfilled;
this.value = value;
this.resolveList.forEach(fn => fn());
}
}
let reject = (reason) => {
if (this.status === Pending) {
this.status = Rejected;
this.reason = reason;
this.rejectList.forEach(fn => fn());
}
}
try {
executor(resolve, reject);
} catch(e) {
reject(e);
}
}
then(onFulfilled, onRejected) {
// onFulfilled = typeof onFulfilled === 'funciton' ? onFulfilled : v => v;
// onRejeced = typeof onRejeced === 'function' ? onRejeced : err => { throw err};
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
//因为错误的值要让后面访问到,所以这里也要跑出个错误,不然会在之后 then 的 resolve 中捕获
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
let promise2 = new Promise((resolve, reject) => {
console.log('promise2', this.status);
// if (this.status === Fulfilled) {
// setTimeout(() => {
// try {
// const data = onFulfilled(this.value);
// console.log(data);
// resolvePromise(promise2, data, resolve, reject);
// } catch(e) {
// reject(e);
// }
// },0);
// }
if (this.status === Fulfilled) {
//Promise/A+ 2.2.2
//Promise/A+ 2.2.4 --- setTimeout
setTimeout(() => {
try {
//Promise/A+ 2.2.7.1
let x = onFulfilled(this.value);
// x可能是一个proimise
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
//Promise/A+ 2.2.7.2
reject(e)
}
}, 0);
}
// if (this.status === Rejected) {
// setTimeout(() => {
// try {
// const data = onRejeced(this.reason);
// resolvePromise(promise2, data, resolve, reject);
// } catch(e) {
// reject(e);
// }
// },0);
// }
if (this.status === Rejected) {
//Promise/A+ 2.2.3
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
}, 0);
}
// if (this.status === Pending) {
// this.resolveList.push(() => {
// setTimeout(() => {
// try {
// const data = onFulfilled(this.value);
// console.log('pending', data);
// resolvePromise(promise2, data, resolve, reject);
// } catch(e) {
// reject(e);
// }
// }, 0);
// });
// this.rejectList.push(() => {
// setTimeout(() => {
// try {
// const data = onRejeced(this.reason);
// resolvePromise(promise2, data, resolve, reject);
// } catch(e) {
// reject(e);
// }
// }, 0);
// });
// }
if (this.status === Pending) {
this.resolveList.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
}, 0);
});
this.rejectList.push(()=> {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0);
});
}
})
return promise2;
}
}
Promise.all = function(arr) {
if (!Array.isArray(arr)) {
const type = typeof arr;
throw new Error(`${type} ${arr} is not iterable`)
}
return new Promise((resolve, reject) => {
let res = [];
let orderIndex = 0;
const processTick = function (item, index) {
res[index] = item;
if (++orderIndex === arr.length) {
resolve(res);
}
}
for(let i = 0; i < arr.length; i++) {
const item = arr[i];
if (item && typeof item.then === 'function') {
item().then((value) => {
processTick(value, i);
}, reject)
} else {
processTick(item, i);
}
}
})
}
Promise.race = function(arr) {
if (!Array.isArray(arr)) {
const type = typeof arr;
throw new Error(`${type} ${arr} is not iterable`)
}
return new Promise((resolve, reject) => {
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
if (item && typeof item.then === 'function') {
item().then(resolve, reject);
} else {
resovle(item);
}
}
})
}
Promise.allSettled = function (arr) {
if (!Array.isArray(arr)) {
const type = typeof arr;
throw new Error(`${type} ${arr} is not iterable`)
}
return new Promise(resolve => {
let res = [];
let orderIndex = 0;
let length = arr.length;
const processTick = (item, index) => {
res[index] = item;
if (++orderIndex === length) {
resolve(res);
}
}
for (let i = 0; i < length; ++i) {
const item = arr[i];
if (item && typeof item.then === 'function') {
item().then((value) => {
processTick({
value,
status: 'fufilled'
}, i)
}, err => {
processTick({
err,
status: 'rejected'
}, i);
})
} else {
processTick({
value: item,
status: 'fufilled'
}, i)
}
}
})
}
// let p = new Promise((res, rej) => {
// console.log('开始异步');
// // res('执行resolve');
// setTimeout(() => {
// console.log('执行resolve');
// res('执行resolve');
// }, 1000);
// });
// p.then(val => {
// console.log('成功', val);
// }, res => {
// console.log('失败', res);
// }).then(val => {
// console.log('再次成功');
// });
const promise = new Promise((resolve, reject) => {
console.log('开始执行');
setTimeout(() => {
// reject('失败');
resolve('成功')
}, 1000);
}).then().then().then(data=>{
console.log('success', data);
},err=>{
console.log('err',err);
})
console