promise的詳細(xì)介紹-來源博客(YK菌)
1、自定義Promise 函數(shù)版本 IIFE
(function (window) {
const PENDING = "pending"
const RESOLVED = "resolved"
const REJECTED = "rejected"
/**promise 構(gòu)造函數(shù) excutor執(zhí)行器函數(shù)*/
function Promise(excutor) {
//給promise對(duì)象指定status屬性,初始值為pending
this.status = PENDING
//給promise對(duì)象指定一個(gè)用于存儲(chǔ)結(jié)果數(shù)據(jù)的屬性
this.data = undefined;
//每個(gè)元素的結(jié)構(gòu) {onResolved(){},onrejected(){}}
this.callbacks = []
let self = this;
function resolve(value) {
//狀態(tài)更改過以后不再執(zhí)行
if (self.status !== PENDING) {
return
}
//更改狀態(tài)
self.status = RESOLVED
//保存value數(shù)據(jù)
self.data = value
//如果有待執(zhí)行cakkback函數(shù),立即異步執(zhí)行回調(diào)函數(shù)
if (self.callbacks.length > 0) {
setTimeout(() => {//放入隊(duì)列中執(zhí)行所有成功的回調(diào)
self.callbacks.forEach(callbacksObj => {
callbacksObj.onResolved(value)
});
})
}
}
function reject(reason) {
//狀態(tài)更改過以后不再執(zhí)行
if (self.status !== PENDING) {
return
}
//更改狀態(tài)
self.status = REJECTED
//保存value數(shù)據(jù)
self.data = reason
//如果有待執(zhí)行cakkback函數(shù),立即異步執(zhí)行回調(diào)函數(shù)
if (self.callbacks.length > 0) {
setTimeout(() => {//放入隊(duì)列中執(zhí)行所有失敗的回調(diào)
self.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(reason)
});
})
}
}
try {
//立即同步執(zhí)行excutor
excutor(resolve, reject)
} catch (error) {//如果執(zhí)行器拋出異常
reject(error)
}
}
/**原型上的then*/
Promise.prototype.then = function (onResolved, onRejected) {
let self = this;
onResolved = typeof onResolved === 'function' ? onResolved : value => value
//實(shí)現(xiàn)異常穿透
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
//返回一個(gè)新的promise對(duì)象
return new Promise((resolve, reject) => {
//調(diào)用指定回調(diào)函數(shù)處理,根據(jù)執(zhí)行結(jié)果,改變r(jià)eturn的promise狀態(tài)
function handle(fn) {
/**
1、如果執(zhí)行拋出異常 return的promise就會(huì)失敗,reason就是error
2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
*/
try {
let result = fn(self.data)
// 3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
if (result instanceof Promise) {
result.then(resolve, reject)
//等價(jià)于
// result.then(
// value => {resolve(value)},
// reason => {reject(reason)}
// )
} else {
// 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
resolve(result)
}
} catch (err) {
reject(err)
}
}
//如果狀態(tài)還沒有被更改此時(shí)緩存回調(diào)函數(shù)
if (self.status === RESOLVED) {
//如果是狀態(tài)已經(jīng)更改過了,回調(diào)函數(shù)放入隊(duì)列中,并改變promise的狀態(tài)
setTimeout(() => {
handle(onResolved)
})
} else if (self.status === REJECTED) {//rejected
//如果是狀態(tài)已經(jīng)更改過了,回調(diào)函數(shù)放入隊(duì)列中
setTimeout(() => {
handle(onRejected)
})
} else {
//當(dāng)前還是pending狀態(tài),保存回調(diào)函數(shù),
self.callbacks.push({
onResolved() {
handle(onResolved)
},
onRejected() {
handle(onRejected)
}
})
}
})
}
/**原型上的catch*/
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected)
}
/**函數(shù)對(duì)象的方法 resolve*/
Promise.resolve = function (value) {
//返回一個(gè)成功或者失敗的promise
return new Promise((resolve, reject) => {
try {
// 3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
if (value instanceof Promise) {
value.then(resolve, reject)
} else {
// 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
resolve(value)
}
} catch (err) {
reject(err)
}
})
}
/**函數(shù)對(duì)象的方法 reject*/
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
/**函數(shù)對(duì)象的方法 all*/
Promise.all = function (promises) {
let list = new Array(promises.length)
let resolvedCount = 0
return new Promise((resolve, reject) => {
//遍歷獲取所有promise的結(jié)果
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {
list[index] = value
resolvedCount++
//如果全部成功,將狀態(tài)置為成功
if (resolvedCount === promises.length) {
resolve(list)
}
},
reason => {//只要有一個(gè)失敗了,return的promise就失敗了
reject(reason)
}
)
})
})
}
/**函數(shù)對(duì)象的方法 race*/
Promise.race = function (promises) {
let resolvedCount = 0
return new Promise((resolve, reject) => {
//遍歷獲取所有promise的結(jié)果
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {
//如果有一個(gè)成功,將狀態(tài)置為成功if (resolvedCount === promises.length) {
resolve(value)
},
reason => {//只要有一個(gè)失敗了,return的promise就失敗了
reject(reason)
}
)
})
})
}
/**自定義函數(shù)對(duì)象的方法 resolveDelay 返回一個(gè)函數(shù)在指定的時(shí)間后才確定結(jié)果*/
Promise.resolveDelay = function (value,time=1000) {
//返回一個(gè)成功或者失敗的promise
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
// 3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
if (value instanceof Promise) {
value.then(resolve, reject)
} else {
// 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
resolve(value)
}
} catch (err) {
reject(err)
}
}, time)
})
}
/**自定義函數(shù)對(duì)象的方法 rejectDelay 返回一個(gè)函數(shù)在指定的時(shí)間后才失敗*/
Promise.rejectDelay = function (value,time=1000) {
setTimeout(() => {
return new Promise((resolve, reject) => {
reject(reason)
})
}, time)
}
window.Promise = Promise
})(window)
2、自定義Promise 類版本
(function (window) {
const PENDING = "pending"
const RESOLVED = "resolved"
const REJECTED = "rejected"
class Promise {
constructor(excutor) {
//給promise對(duì)象指定status屬性,初始值為pending
this.status = PENDING
//給promise對(duì)象指定一個(gè)用于存儲(chǔ)結(jié)果數(shù)據(jù)的屬性
this.data = undefined;
//每個(gè)元素的結(jié)構(gòu) {onResolved(){},onrejected(){}}
this.callbacks = []
let self = this;
function resolve(value) {
//狀態(tài)更改過以后不再執(zhí)行
if (self.status !== PENDING) {
return
}
//更改狀態(tài)
self.status = RESOLVED
//保存value數(shù)據(jù)
self.data = value
//如果有待執(zhí)行cakkback函數(shù),立即異步執(zhí)行回調(diào)函數(shù)
if (self.callbacks.length > 0) {
setTimeout(() => {//放入隊(duì)列中執(zhí)行所有成功的回調(diào)
self.callbacks.forEach(callbacksObj => {
callbacksObj.onResolved(value)
});
})
}
}
function reject(reason) {
//狀態(tài)更改過以后不再執(zhí)行
if (self.status !== PENDING) {
return
}
//更改狀態(tài)
self.status = REJECTED
//保存value數(shù)據(jù)
self.data = reason
//如果有待執(zhí)行cakkback函數(shù),立即異步執(zhí)行回調(diào)函數(shù)
if (self.callbacks.length > 0) {
setTimeout(() => {//放入隊(duì)列中執(zhí)行所有失敗的回調(diào)
self.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(reason)
});
})
}
}
try {
//立即同步執(zhí)行excutor
excutor(resolve, reject)
} catch (error) {//如果執(zhí)行器拋出異常
reject(error)
}
}
/**原型上的then*/
then(onResolved, onRejected) {
let self = this;
onResolved = typeof onResolved === 'function' ? onResolved : value => value
//實(shí)現(xiàn)異常穿透
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
//返回一個(gè)新的promise對(duì)象
return new Promise((resolve, reject) => {
//調(diào)用指定回調(diào)函數(shù)處理,根據(jù)執(zhí)行結(jié)果,改變r(jià)eturn的promise狀態(tài)
function handle(fn) {
/**
1、如果執(zhí)行拋出異常 return的promise就會(huì)失敗,reason就是error
2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
*/
try {
let result = fn(self.data)
// 3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
if (result instanceof Promise) {
result.then(resolve, reject)
//等價(jià)于
// result.then(
// value => {resolve(value)},
// reason => {reject(reason)}
// )
} else {
// 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
resolve(result)
}
} catch (err) {
reject(err)
}
}
//如果狀態(tài)還沒有被更改此時(shí)緩存回調(diào)函數(shù)
if (self.status === RESOLVED) {
//如果是狀態(tài)已經(jīng)更改過了,回調(diào)函數(shù)放入隊(duì)列中,并改變promise的狀態(tài)
setTimeout(() => {
handle(onResolved)
})
} else if (self.status === REJECTED) {//rejected
//如果是狀態(tài)已經(jīng)更改過了,回調(diào)函數(shù)放入隊(duì)列中
setTimeout(() => {
handle(onRejected)
})
} else {
//當(dāng)前還是pending狀態(tài),保存回調(diào)函數(shù),
self.callbacks.push({
onResolved() {
handle(onResolved)
},
onRejected() {
handle(onRejected)
}
})
}
})
}
/**原型上的catch*/
catch(onRejected) {
return this.then(undefined, onRejected)
}
/**函數(shù)對(duì)象的方法 resolve*/
static resolve = function (value) {
//返回一個(gè)成功或者失敗的promise
return new Promise((resolve, reject) => {
try {
// 3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
if (value instanceof Promise) {
value.then(resolve, reject)
} else {
// 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
resolve(value)
}
} catch (err) {
reject(err)
}
})
}
/**函數(shù)對(duì)象的方法 reject*/
static reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
/**函數(shù)對(duì)象的方法 all*/
static all = function (promises) {
let list = new Array(promises.length)
let resolvedCount = 0
return new Promise((resolve, reject) => {
//遍歷獲取所有promise的結(jié)果
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {
list[index] = value
resolvedCount++
//如果全部成功,將狀態(tài)置為成功
if (resolvedCount === promises.length) {
resolve(list)
}
},
reason => {//只要有一個(gè)失敗了,return的promise就失敗了
reject(reason)
}
)
})
})
}
/**函數(shù)對(duì)象的方法 race*/
static race = function (promises) {
let resolvedCount = 0
return new Promise((resolve, reject) => {
//遍歷獲取所有promise的結(jié)果
promises.forEach((p, index) => {
Promise.resolve(p).then(
value => {
//如果有一個(gè)成功,將狀態(tài)置為成功if (resolvedCount === promises.length) {
resolve(value)
},
reason => {//只要有一個(gè)失敗了,return的promise就失敗了
reject(reason)
}
)
})
})
}
/**自定義函數(shù)對(duì)象的方法 resolveDelay 返回一個(gè)函數(shù)在指定的時(shí)間后才確定結(jié)果*/
static resolveDelay = function (value, time = 1000) {
//返回一個(gè)成功或者失敗的promise
return new Promise((resolve, reject) => {
setTimeout(() => {
try {
// 3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
if (value instanceof Promise) {
value.then(resolve, reject)
} else {
// 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
resolve(value)
}
} catch (err) {
reject(err)
}
}, time)
})
}
/**自定義函數(shù)對(duì)象的方法 rejectDelay 返回一個(gè)函數(shù)在指定的時(shí)間后才失敗*/
static ejectDelay = function (value, time = 1000) {
setTimeout(() => {
return new Promise((resolve, reject) => {
reject(reason)
})
}, time)
}
}
window.Promise = Promise
})(window)
3、promise.all中,其中一個(gè)promise出錯(cuò),如何確保執(zhí)行到最后
let p1 = new Promise((resolve, reject) => {
resolve("p1");
});
let p2 = new Promise((resolve, reject) => {
resolve("p2");
});
let p3 = new Promise((resolve, reject) => {
reject("p3");
});
Promise.all([p1, p2, p3])
.then((res) => {
console.log("res:", res);
})
.catch((err) => {
console.log("err:", err);
});
//執(zhí)行結(jié)果為 err: p3
//改寫一下,主動(dòng)去獲取報(bào)錯(cuò),然后自定義出錯(cuò)后的返回值,例子中如果使用null作為返回值的話
Promise.all([p1, p2, p3].map((p) => p.catch((e) => 出錯(cuò)后的返回值)))
.then((res) => {
console.log("res:", res);
})
.catch((err) => {
console.log("err:", err);
});
//執(zhí)行結(jié)果為 res: ['p1', 'p2', null]