Promise/A+規範實現Promise,promises-aplus-tests
測試經過。數組
const PENDING = "PENDING"
const FULFILLED = "FULFILLED"
const REJECTED = "REJECTED"
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
return reject(new TypeError(`Chaining cycle detected for promise #<Promise>`));
}
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
let then, called;
try {
then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true
resolvePromise(promise2, y, resolve, reject)
}, r => {
if (called) return;
called = true
reject(r)
})
} else {
resolve(x)
}
} catch (e) {
if (called) return;
called = true
reject(e)
}
} else {
resolve(x)
}
}
const isPromise = (value) => {
if ((typeof value === 'object' && value !== null) || typeof value === 'function') {
return typeof value.then === 'function'
}
return false
}
class Promise {
constructor(executor) {
this.status = PENDING
this.value = undefined
this.reason = undefined
this.onFulfilledCallBack = []
this.onRejectedCallBack = []
const resolve = (value) => {
if (value instanceof Promise) {
return value.then(resolve, reject)
}
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value
this.onFulfilledCallBack.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
this.onRejectedCallBack.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => { return value; }
onRejected = typeof onRejected === 'function' ? onRejected : (err) => { throw err; }
let promise2 = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === PENDING) {
this.onFulfilledCallBack.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
this.onRejectedCallBack.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
})
return promise2
}
catch(errCallBack) {
return this.then(null, errCallBack)
}
finally(callback) {
return this.then(value => {
return Promise.resolve(callback()).then(() => value)
}, err => {
return Promise.resolve(callback()).then(() => { throw err; })
})
}
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value)
})
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
static all(promises) {
return new Promise((resolve, reject) => {
let arr = [], i = 0;
let processData = (index, data) => {
arr[i] = data
if (++i === promises.length) {
resolve(arr)
}
}
if (promises instanceof Array) {
promises.forEach((p, index) => {
if (isPromise(p)) {
p.then((data) => {
processData(index, data)
}, reject)
} else {
processData(index, p)
}
})
} else {
reject()
}
})
}
static race(promises) {
return new Promise((resolve, reject) => {
if (promises instanceof Array) {
for (let i = 0; i < promises.length; i++) {
let current = promises[i]
if (isPromise(current)) {
if (current.value || (!isPromise(current.value) && current.status !== PENDING)) {
resolve(current.value)
}
current.then(resolve, reject)
} else {
resolve(current)
}
}
} else {
reject()
}
})
}
static try(callback) {
return new Promise((resolve, reject) => {
return Promise.resolve(callback()).then(resolve)
})
}
}
Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject
})
return dfd;
}
module.exports = Promise
/**
* 根據Promise/A+規範
* 實現Promise步驟解析:
* 1.Promise的構造函數接收一個函數
* executor(resolve, reject)
* 接收2個參數
* resolve 成功後執行函數,改變value和status
* reject 失敗後執行函數,改變reason和status
* 注意:
* 1.一旦建立它就會當即執行,中途沒法取消
* 2.一旦狀態改變就不會在變
* 3.若是resolve接收的是一個promise,就讓它執行then方法而且採用它的狀態
* 4.若是拋出異常,須要處理異常狀況
* 2.Promise實例生成後,用then方法指定fulfilled 和 rejected狀態的回調
* 1).同步函數
* 直接判斷status的狀態,分別調用onFulfilled或onRjected
* 2).異步函數
* 須要用到訂閱發佈模式
* 定義兩個數組分別保存fulfilled 和 rejected的回調函數,
* 再異步執行到resolve或reject的時候,
* 改變狀態獲取value或reason,
* 再去執行數組中保存的回調函數
* 3.promise的鏈式調用
* 特色:
* 1).then中返回一個新的promise對象
* promise2 = new Promise(executor);
return promise2;
* 2).鏈式調用中,下一個then的狀態採用它上一個then的返回
* 須要保存第一個then返回的值,
* a.若是第一個then返回的是普通值(除function,object),會走下一個then的成功
* b.若是第一個then拋出錯誤,會走下一個then的失敗
* c.若是第一個then返回的是一個promise,就讓它執行而且採用它的狀態
* 此過程須要遞歸,直到再沒有promise爲止
* 注意:
* 1.onFulfilled 和 onRejected 不能在當前上下文執行
* 解決辦法:使用setTimeout
* 使用setTimeout的還有一個目的:保證能拿到promise2
* 2.then中2個回調都不存在時的處理
* 解決辦法:不存在時,須要本身提供默認的函數
* 4.catch的實現
* catch的原理:成功回調函數爲null時的then方法
* then(null,onRejected)
* 5.all
* 原理:
* 1).返回一個新的Promise實例(全部的都成功才成功,有一個失敗就失敗)
* 2).接收一個數組,數組中都是Promise實例,
* 若是不是,就會先調用Promise.resolve方法,將參數轉爲 Promise 實例,再進一步處理。
* 3).只有數組中全部的promise的狀態都變成fulfilled,狀態纔會變成fulfilled,返回值組成一個數組,傳遞給外層的回調函數。
4).只要數組中有一個是rejected,狀態就變成rejected,此時第一個被reject的實例的返回值,會傳遞給外層的回調函數。
* 6.finally
原理:
1).不管如何都執行
若是回調函數中返回promise,等待promise執行完畢,再走下一個then/catch(捕獲finally上一個then的成功和失敗)
* 7.race
* 原理:
* 1).返回一個新的Promise實例
* 2).接收一個數組,數組中都是Promise實例,
* 若是不是,就會先調用Promise.resolve方法,將參數轉爲 Promise 實例,再進一步處理。
* 3).promise數組中誰快返回誰的結果 *
* 8.Promise.resolve和Promise.reject的實現
* Promise.resolve原理:返回一個成功的Promise
* Promise.reject原理:返回一個失敗的Promise
* 9.Promise.try
* 原理:
* 1).無論是同步仍是異步錯誤都能捕獲
*/
複製代碼