自定義Promise實現(xiàn)拯爽,來了解他的運行原理
function MyPromise(executor) {
// 添加屬性
this.promiseState = 'pendding'; // 默認(rèn)值是pendding
this.promiseResult = null;
// this.callback = {}; // 會存在覆蓋的情況
this.callbacks = []; // 應(yīng)該使用數(shù)組去存所有的回調(diào)
const self = this;
// resolve函數(shù)
function resolve(data) {
// 狀態(tài)只能改一次
if(self.promiseState =='pendding') {
// 這里的this是window
// 1 修改對象狀態(tài)promiseState 屬于實例對象
self.promiseState = 'fullfilled'
// 2 設(shè)置對象結(jié)果值promiseResult 屬于實例對象
self.promiseResult = data
// 這里執(zhí)行回調(diào) 異步的時候處理, 這里有缺陷牡属,可以有多個回調(diào)
// if(self.callback.onResolved) {
// self.callback.onResolved();
// }
// 保證回調(diào)時異步執(zhí)行的
setTimeout(() => {
self.callbacks.forEach(item => {
item.onResolved()
})
})
}
}
// reject函數(shù)
function reject(data) {
if(self.promiseState =='pendding') {
// 1 修改對象狀態(tài)promiseState 屬于實例對象
self.promiseState = 'rejected'
// 2 設(shè)置對象結(jié)果值promiseResult 屬于實例對象
self.promiseResult = data
// if(self.callback.onRejected) {
// self.callback.onRejected();
// }
setTimeout(() => {
self.callbacks.forEach(item => {
item.onRejected()
})
})
// self.callbacks.forEach(item => {
// item.onRejected()
// })
}
}
// 這里應(yīng)該加try-catch伞鲫, 目的是在拋出錯誤的時候 同樣能夠改變狀態(tài)
try{
// 同步執(zhí)行executor
executor(resolve, reject); // resolve,和reject是函數(shù)內(nèi)部使用的丙号,因此應(yīng)該在內(nèi)部聲明
} catch(e) {
// 修改promise對象狀態(tài)為失敗
reject(e);
}
}
// 添加then方法
// MyPromise.prototyep.then = function(onResolved, onRejected) {
// // 調(diào)用回調(diào)函數(shù),是有條件的通過promiseState 來判斷
// if(this.promiseState =='fullfilled') {
// onResolved(this.promiseResult);
// }
// if(this.promiseState == 'rejected') {
// onRejected(this.promiseResult);
// }
// if(this.promiseState == 'pendding') {
// // 保存回調(diào)函數(shù)乏梁, 因為這里狀態(tài)不確定,不能直接調(diào)用回調(diào),應(yīng)該先保存下來似炎,在狀態(tài)改變的時候去調(diào)用荧飞, 因此在實例對象上聲明一個屬性callback = {}
// // this.callback = { // 這種寫法有瑕疵,因為可以指定多個回調(diào)名党,而這種方式會覆蓋之前的回調(diào),應(yīng)該用一個數(shù)組去存將this.callback 該為this.callbacks
// // onResolved:onResolved,
// // onRejected: onRejected
// // }
// // 緩存所有的回調(diào)
// this.callbacks.push({
// onResolved:onResolved,
// onRejected: onRejected
// })
// }
// }
// then方法應(yīng)該返回promsie對象, 該實現(xiàn)由很多重復(fù)代碼挠轴,應(yīng)該優(yōu)化
// MyPromise.prototyep.then = function(onResolved, onRejected) {
// const self = this;
// return new MyPromise((resolve, reject) => {
// // 調(diào)用回調(diào)函數(shù),是有條件的通過promiseState 來判斷
// if(this.promiseState =='fullfilled') {
// // 獲取回調(diào)函數(shù)的執(zhí)行結(jié)果
// // 解決拋出異常時改變狀態(tài)
// try{
// let result = onResolved(this.promiseResult);
// if(result instanceof MyPromise) {
// result.then(v => {
// resolve(v);
// }, r => {
// reject(r)
// })
// } else {
// // 結(jié)果的對象狀態(tài)變?yōu)槌晒?// resolve(result);
// }
// }catch(e) {
// reject(e)
// }
// }
// if(this.promiseState == 'rejected') {
// // 解決拋出異常時改變狀態(tài)
// try{
// let result = onRejected(this.promiseResult);
// if(result instanceof MyPromise) {
// result.then(v => {
// resolve(v);
// }, r => {
// reject(r)
// })
// } else {
// // 結(jié)果的對象狀態(tài)變?yōu)槌晒?// resolve(result);
// }
// }catch(e) {
// reject(e)
// }
// }
// if(this.promiseState == 'pendding') {
// // 保存回調(diào)函數(shù)传睹, 因為這里狀態(tài)不確定,不能直接調(diào)用回調(diào),應(yīng)該先保存下來岸晦,在狀態(tài)改變的時候去調(diào)用欧啤, 因此在實例對象上聲明一個屬性callback = {}
// // this.callback = { // 這種寫法有瑕疵,因為可以指定多個回調(diào)启上,而這種方式會覆蓋之前的回調(diào)邢隧,應(yīng)該用一個數(shù)組去存將this.callback 該為this.callbacks
// // onResolved:onResolved,
// // onRejected: onRejected
// // }
// // 緩存所有的回調(diào), 異步回調(diào)的時候這種寫法也有問題
// // this.callbacks.push({
// // onResolved:onResolved,
// // onRejected: onRejected
// // })
// this.callbacks.push({
// onResolved: function() {
// try{
// console.log('success')
// // 執(zhí)行成功的回調(diào)函數(shù),根據(jù)其結(jié)果改變狀態(tài)
// let result = onResolved(self.promiseResult)
// if(result instanceof MyPromise) {
// result.then(v => {
// resolve(v);
// }, r => {
// reject(r);
// })
// } else{
// resolve(resulte)
// }
// }catch(e){
// reject(e)
// }
// },
// onRejected: function () {
// try{
// let result = onRejected(self.promiseResult)
// if(result instanceof MyPromise) {
// result.then(v => {
// resolve(v);
// }, r => {
// reject(r);
// })
// } else{
// resolve(resulte)
// }
// }catch(e){
// reject(e);
// }
// }
// })
// }
// })
// }
// 優(yōu)化then方法
MyPromise.prototyep.then = function(onResolved, onRejected) {
const self = this;
// 判斷回調(diào)函數(shù)
if(typeof onRejected !== 'function') { // 這里給定默認(rèn)值是因為在發(fā)生錯誤的時候會調(diào)用該函數(shù),
onRejected = reason => {
throw reason
}
}
if(typeof onResolved !== 'function') { // 這里給定默認(rèn)值是因為在發(fā)生錯誤的時候會調(diào)用該函數(shù)冈在,
onResolved = value => value;
}
return new MyPromise((resolve, reject) => {
// 封裝函數(shù)
function callback(type) {
try{
let result = type(self.promiseResult);
if(result instanceof MyPromise) {
result.then(v => {
resolve(v);
}, r => {
reject(r)
})
} else {
// 結(jié)果的對象狀態(tài)變?yōu)槌晒? resolve(result);
}
}catch(e) {
reject(e)
}
}
// 調(diào)用回調(diào)函數(shù),是有條件的通過promiseState 來判斷
if(this.promiseState =='fullfilled') {
// 獲取回調(diào)函數(shù)的執(zhí)行結(jié)果
// 解決拋出異常時改變狀態(tài)
setTimeout(function () {
callback(onResolved)
})
}
if(this.promiseState == 'rejected') {
// 解決拋出異常時改變狀態(tài)
setTimeout(function () {
callback(onRejected)
})
}
if(this.promiseState == 'pendding') {
// 保存回調(diào)函數(shù)倒慧, 因為這里狀態(tài)不確定,不能直接調(diào)用回調(diào),應(yīng)該先保存下來包券,在狀態(tài)改變的時候去調(diào)用纫谅, 因此在實例對象上聲明一個屬性callback = {}
// this.callback = { // 這種寫法有瑕疵,因為可以指定多個回調(diào)溅固,而這種方式會覆蓋之前的回調(diào)付秕,應(yīng)該用一個數(shù)組去存將this.callback 該為this.callbacks
// onResolved:onResolved,
// onRejected: onRejected
// }
// 緩存所有的回調(diào), 異步回調(diào)的時候這種寫法也有問題
// this.callbacks.push({
// onResolved:onResolved,
// onRejected: onRejected
// })
this.callbacks.push({
onResolved: function() {
callback(onResolved)
},
onRejected: function () {
callback(onRejected)
}
})
}
})
}
// 添加catch方法
MyPromise.promiseState.catch = function (onRejected) {
return this.then(undefined, onRejected)
}
// MyPromise.resolve() 快速創(chuàng)建一個promise對象
MyPromise.resolve = function (value) {
return new MyPromise((resolve, reject) => {
if(value instanceof MyPromise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
// 設(shè)置狀態(tài)為成功
resolve(value)
}
})
}
MyPromise.reject = function (reason){
return MyPromise((reason, reject) => {
reject(reason)
})
}
// Promise.all
MyPromise.all = function (promises) {
return new MyPromise((resolve, reject) => {
let count = 0;
let arr = []; // 存結(jié)果
for(let i = 0; i < promises.length; i++) {
promises[i].then(v=>{
// resolve() 這里直接調(diào)用不對,應(yīng)該三個都成功才能resolve
count++;
arr[i] = v;
if(count === promises.length) { // 說明都成功了
resolve(arr);
}
}, r=>{
reject();
})
}
})
}
MyPromise.race = function (promises) {
return MyPromise((resolve, reject) => {
for(let i = 0; i < promises.length; i++) {
promises[i].then(v=>{
resolve(v); // 誰先運行誰先決定結(jié)果
}, r=>{
reject();
})
}
})
}