手寫promise
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
function MyPromise(fn) {
// 保存初始化狀態
var self = this
// 初始化狀態
this.state = PENDING
// 用於保存 resolve 或者 rejected 傳入的值
this.value = null
// 用於保存 resolve 的回調函數
this.resolvedCallbacks = []
// 用於保存 reject 的回調函數
this.rejectedCallbacks = []
// 狀態轉變爲 resolved 方法
function resolve(value) {
// 判斷傳入元素是否爲 Promise 值,若是是,則狀態改變必須等待前一個狀態改變後再進行改變
if (value instanceof MyPromise) {
return value.then(resolve, reject)
}
// 保證代碼的執行順序爲本輪事件循環的末尾
setTimeout(() => {
// 只有狀態爲 pending 時才能轉變,
if (self.state === PENDING) {
// 修改狀態
self.state = RESOLVED
// 設置傳入的值
self.value = value
// 執行回調函數
self.resolvedCallbacks.forEach((callback) => {
callback(value)
})
}
}, 0)
}
// 狀態轉變爲 rejected 方法
function reject(value) {
// 保證代碼的執行順序爲本輪事件循環的末尾
setTimeout(() => {
// 只有狀態爲 pending 時才能轉變
if (self.state === PENDING) {
// 修改狀態
self.state = REJECTED
// 設置傳入的值
self.value = value
// 執行回調函數
self.rejectedCallbacks.forEach((callback) => {
callback(value)
})
}
}, 0)
}
// 將兩個方法傳入函數執行
try {
fn(resolve, reject)
} catch (e) {
// 遇到錯誤時,捕獲錯誤,執行 reject 函數
reject(e)
}
}
MyPromise.prototype.then = function (onResolved, onRejected) {
// 首先判斷兩個參數是否爲函數類型,由於這兩個參數是可選參數
onResolved =
typeof onResolved === 'function'
? onResolved
: function (value) {
return value
}
onRejected =
typeof onRejected === 'function'
? onRejected
: function (error) {
throw error
}
// 若是是等待狀態,則將函數加入對應列表中
if (this.state === PENDING) {
this.resolvedCallbacks.push(onResolved)
this.rejectedCallbacks.push(onRejected)
}
// 若是狀態已經凝固,則直接執行對應狀態的函數
if (this.state === RESOLVED) {
onResolved(this.value)
}
if (this.state === REJECTED) {
onRejected(this.value)
}
}
手寫Promise.all()
Promise.all = function(iterator) {
if (!Array.isArray(iterator)) return;
let count = 0;
let res = [];
return new Promise((resolve, reject) => {
for(let item of iterator) {
Promise.resolve(item)
.then(data => {
res[count++] = data;
if (count === iterator.length) {
resolve(res);
}
})
.catch(e => {
reject(e);
})
}
})
}
// test
let p1 = Promise.resolve(3);
let p2 = 4;
let p3 = new Promise(resolve => {
setTimeout(resolve, 100, 'lee')
// setTimeout的第三個日後參數都是用來做爲第一個參數也就是函數的參數,也就是實際上是setTimeout(resolve('lee'), 100)
});
Promise.all([p1, p2, p3]).then(data => {
console.log(data);
})
手寫Promise.race()
Promise.race = function(iterator) {
return new Promise((resolve, reject) => {
for(let item of iterator) {
Promise.resolve(item)
.then(data => {
resolve(data)
})
.catch(e => {
reject(e)
})
}
})
}
let p1 = new Promise(resolve => {
setTimeout(resolve, 105, 'p1 done')
})
let p2 = new Promise(resolve => {
setTimeout(resolve, 100, 'p2 done')
})
Promise.race([p1, p2]).then(data => {
console.log(data); // p2 done
})