1. Promise.all()方法:
返回全部成功結(jié)果的數(shù)組值隐孽,如果有報(bào)錯(cuò),立即返回reject,結(jié)束。
// all 方法:全部成功返回一個(gè)數(shù)組穷娱,失敗就返回失敗的值
myPromise.all = (values) => {//傳入的是一個(gè)數(shù)組 [p1,p2]
return new myPromise((resolve, reject) => {
let results = [];
let i = 0;
let processData = (value, index) => {
results[index] = value;
i++;
if (i === values.length) {
resolve(results)
}
}
for (let i = 0; i < values.length; i++) {
//獲取當(dāng)前的函數(shù)
let current = values[i];
//判斷是函數(shù)還是變量
if (typeof current === 'function' || (typeof current === 'object' && typeof current !== null)) {
if (typeof current.then === 'function') {
current.then(y => {
processData(y, i)
}, err => {
reject(err); //只要有一個(gè)傳入的promise沒有執(zhí)行成功就走 reject
return;
})
} else {
//常量
processData(values[i], i)
}
}
}
})
}
2. Promise.race()方法:
返回第一個(gè)結(jié)果,不管成功或失敗翘地。
// race 方法:先快執(zhí)行誰冕碟,然后返回
myPromise.race = (values) => {//傳入的是一個(gè)數(shù)組[p1,p2]
return new myPromise((resolve, reject) => {
for (let i = 0; i < values.length; i++) {
let current = values[i];
if (typeof current === 'function' || (typeof current === 'object' && typeof current !== null)) {
current.then(y => {
resolve(y)
return
}, err => {
reject(err)
return
})
} else {
resolve(current)
}
}
})
}
3.源碼
class myPromise {
constructor(executor) {
this.state = 'pending'; //狀態(tài)值
this.value = undefined; //成功的返回值
this.reason = undefined; //失敗的返回值
this.onResolveCallbacks = []; //成功的回調(diào)函數(shù)
this.onRejectCallbacks = []; //失敗的回調(diào)函數(shù)
//成功
let resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fullFilled'
this.value = value
this.onResolveCallbacks.forEach(fn => fn())
}
}
//失敗
let reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.onRejectCallbacks.forEach(fn => fn())
}
}
try {
//執(zhí)行函數(shù)
executor(resolve, reject)
} catch (err) {
//失敗則直接執(zhí)行reject函數(shù)
reject(err)
}
}
then(onFullfilled, onRejected) {
// then 返回一個(gè)promise ,這樣就是一個(gè)遞歸
let promise2 = new myPromise((resolve, reject) => {
let x;
if (this.state === 'fullFilled') {
//同步憎亚,狀態(tài)為fullfilled,執(zhí)行 onFullfilled,傳入成功的值
setTimeout(() => {
try {
x = onFullfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
//中間任何一個(gè)環(huán)節(jié)報(bào)錯(cuò)都走reject
reject(error)
}
}, 0)//同步無法使用promise2员寇,所以借用setTimeout異步的方式。
}
if (this.state === 'rejected') {
//異步第美,rejected,執(zhí)行 onRejected,傳入失敗的值
setTimeout(() => {
try {
x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
//中間任何一個(gè)環(huán)節(jié)報(bào)錯(cuò)都走reject
reject(error)
}
}, 0)//同步無法使用promise2蝶锋,所以借用setTimeout異步的方式。
}
//異步
if (this.state === 'pending') {
this.onResolveCallbacks.push(() => {
setTimeout(() => {
try {
x = onFullfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
//中間任何一個(gè)環(huán)節(jié)報(bào)錯(cuò)都走reject
reject(error)
}
}, 0)//同步無法使用promise2什往,所以借用setTimeout異步的方式扳缕。
})
this.onRejectCallbacks.push(() => {
setTimeout(() => {
try {
x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
//中間任何一個(gè)環(huán)節(jié)報(bào)錯(cuò)都走reject
reject(error)
}
}, 0)//同步無法使用promise2,所以借用setTimeout異步的方式别威。
})
}
})
return promise2;//返回promise
}
finally(callback) {
return this.then(callback, callback)
}
catch(rejectFuc) {
return this.then(null, rejectFuc);
}
}
// 這個(gè)方法的主要左右是用來判斷x的值躯舔,如果x的值是一個(gè)普通的值,就直接返回x的值省古,如果x的值是一個(gè)promise粥庄,就要返回x.then()執(zhí)行的結(jié)果,核心代碼如下
const resolvePromise = (promise2, x, resolve, reject) => {
// x和promise2不能是同一個(gè)豺妓,如果是同一個(gè)就報(bào)錯(cuò)
if (promise2 === x) {
return reject(
new TypeError('Chaining cycle detected for promise #<promise>')
)
}
// 判斷x是否是一個(gè)對(duì)象惜互,判斷函數(shù)是否是對(duì)象的方法有: typeof instanceof constructor toString
if (typeof x === 'object' && x != null || typeof x === 'function') {
let called;
try {
let then = x.then; //取 then可以報(bào)錯(cuò)布讹,報(bào)錯(cuò)就走 reject();
if (typeof then === 'function') {
then.call(x, y => {
console.log('y', y);
if (called) return;
called = true;
resolve(y); //采用promise的成功結(jié)果,并且向下傳遞
resolvePromise(promise2, y, resolve, reject)
}, r => {
if (called) return;
called = true;
reject(r);//采用promise的成功結(jié)果训堆,并且向下傳遞
})
} else {
resolve(x); //x不是一個(gè)函數(shù)炒事,是一個(gè)對(duì)象
}
} catch (error) {
if (called) return;
called = true;
reject(error);//報(bào)錯(cuò)就走 reject();
}
} else {
// x是一個(gè)普通值
resolve(x)
}
}
myPromise.resolve = (value) => {
return new myPromise((resolve, reject) => {
resolve(value)
})
}
myPromise.reject = (value) => {
return new myPromise((resolve, reject) => {
reject(value)
})
}
// all 方法:全部成功返回一個(gè)數(shù)組,失敗就返回失敗的值
myPromise.all = (values) => {//傳入的是一個(gè)數(shù)組 [p1,p2]
return new myPromise((resolve, reject) => {
let results = [];
let i = 0;
let processData = (value, index) => {
results[index] = value;
i++;
if (i === values.length) {
resolve(results)
}
}
for (let i = 0; i < values.length; i++) {
//獲取當(dāng)前的函數(shù)
let current = values[i];
//判斷是函數(shù)還是變量
if (typeof current === 'function' || (typeof current === 'object' && typeof current !== null)) {
if (typeof current.then === 'function') {
current.then(y => {
processData(y, i)
}, err => {
reject(err); //只要有一個(gè)傳入的promise沒有執(zhí)行成功就走 reject
return;
})
} else {
//常量
processData(values[i], i)
}
}
}
})
}
// race 方法:先快執(zhí)行誰蔫慧,然后返回
myPromise.race = (values) => {//傳入的是一個(gè)數(shù)組[p1,p2]
return new myPromise((resolve, reject) => {
for (let i = 0; i < values.length; i++) {
let current = values[i];
if (typeof current === 'function' || (typeof current === 'object' && typeof current !== null)) {
current.then(y => {
resolve(y)
return
}, err => {
reject(err)
return
})
} else {
resolve(current)
}
}
})
}
let p = new myPromise((resolve, reject) => {
// resolve('成功') //走了成功就不會(huì)走失敗
// throw new Error('失敗了');
// reject('failed') // 走了失敗就不會(huì)走成功
setTimeout(() => {
resolve('success')
}, 0)
})
p.then(res => {
console.log(res);
}, err => {
console.log(err);
})
console.log(p);