為什么用Promise?
- Promise能解決回調地獄問題
- Promise能多個異步操作并行炮叶,獲取最終結果
Promise三種狀態(tài)
- Pending Promise對象實例創(chuàng)建時候的初始狀態(tài)
- Fulfilled 可以理解為成功的狀態(tài)
- Rejected 可以理解為失敗的狀態(tài)
Promise狀態(tài)轉換
image
Promise一旦從pending狀態(tài)到resolve狀態(tài)或者reject狀態(tài)就不會再改變哥遮,能保證結果的正確性笨使,不會出現從成功到失敗或者從失敗到成功的情況镀裤。
原生Promise使用分析
let promise = new Promise((resolve,reject)=>{
resolve("xxx")
reject("sssss")
})
promise.then(res=>{
console.log("success",res);
},e=>{
console.log("fail",e);
})
Promise
Promise
創(chuàng)建一個Promise需要傳遞一個
executor
回調函數作為參數,來初始化Promise缴饭。executor
中有兩個參數暑劝,一個resolve用來回調返回值或者另一個Promise,一個reject用來回調失敗值或者Error颗搂。
then()
then函數
then函數需傳遞兩個函數作為參數担猛,一個回調resolve的結果,一個回調reject的結果
const STATUS = {
"PENDING": "pending",
"FULFILLED": "fulfilled",
"REJECTED": "rejected"
}
class Promise {
/**
* Creates a new Promise.
*
* @param executor — A callback used to initialize the promise.
* This callback is passed two arguments: a resolve callback used to resolve the promise
* with a value or the result of another promise, and a reject callback used to reject the
* promise with a provided reason or error.
*/
constructor(executor) {
this.status = STATUS.PENDING;
this.value = undefined;
this.reason = undefined;
const resolve = (value) => {
if (this.status === STATUS.PENDING) {
this.status = STATUS.FULFILLED;
this.value = value;
}
};
const reject = (reason) => {
if (this.status === STATUS.PENDING) {
this.status = STATUS.REJECTED;
this.reason = reason;
}
};
try {
executor(resolve, reject);
} catch (error) {
}
}
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled — The callback to execute when the Promise is resolved.
* @param onrejected — The callback to execute when the Promise is rejected.
* @returns — A Promise for the completion of which ever callback is executed.
*/
then(onfulfilled,onrejected) {
if(this.status === STATUS.FULFILLED){
onfulfilled(this.value)
}
if(this.status === STATUS.REJECTED){
onrejected(this.reason)
}
}
}
module.exports = Promise;
let promise = new Promise((resolve,reject)=>{
resolve("xxx")
reject("sssss")
})
promise.then(res=>{
console.log("success",res);
},e=>{
console.log("fail",e);
})
//success xxx
現在我們實現了一個簡單的Promise丢氢,可以在Promise中通過resolve函數傳遞普通值到then函數中傅联,并在then的onfullfilled中取出,或者通過reject傳遞在onrejected中取出疚察。并且實現Promise狀態(tài)從pendding到resolve或reject,不可逆蒸走。
實現鏈式調用
then(onfulfilled,onrejected) {
let promise2 = new Promise((resolve,reject)=>{
if(this.status === STATUS.FULFILLED){
let x = onfulfilled(this.value)
resolve(x)
}
if(this.status === STATUS.REJECTED){
let x = onrejected(this.reason)
reject(x)
}
if(this.status === STATUS.PENDING){
this.onResolvedCallbacks.push(()=>{
onfulfilled(this.value);
});
this.onrejectedCallbacks.push(()=>{
onrejected(this.reason);
});
}
});
return promise2;
}
const resolve = (value) => {
if (this.status === STATUS.PENDING) {
this.status = STATUS.FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach(fn=>fn());
}
};
const reject = (reason) => {
if (this.status === STATUS.PENDING) {
this.status = STATUS.REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach(fn=>fn());
}
};
let promise = new Promise((resolve,reject)=>{
resolve("xxx")
reject("sssss")
})
promise.then(res=>{
console.log("success",res);
return "next"
},e=>{
console.log("fail",e);
}).then(res=>{
console.log("success1",res)
})
//success xxx
//success1 next
處理返回值是Promise的情況 resolvePromise函數的實現
//解析x類型,決定promise2走成功還是失敗
function resolvePromise(promise2, x, resolve, reject) {
console.log("x", x)
if (x === promise2) {
return reject(new TypeError("返回值錯誤貌嫡,不能使用同一個promise"))
}
//只有object或者function才能是Promise
if ((typeof x === 'object' && typeof x != null) || typeof x === 'function') {
let called = false;//成功或者失敗方法只能調用一次比驻,防止其他Promise實現錯誤
try {
let then = x.then;//通過判斷x上是否有then函數,判斷x是否是一個Promise
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
// resolve(y) y有可能還是promise 遞歸解析 直到是普通值為止
resolvePromise(promise2, y, resolve, reject);
}, r => {
if (called) return;
called = true;
reject(r);
})
} else {
reject(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
reject(x);
}
}
引入Promise A+ 單元測試
Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
})
return dfd;
}
npm install promises-aplus-tests
promises-aplus-tests myPromise.js
單元測試
如果單元測試通過岛抄,證明我們的Promise符合Promise A+規(guī)范
完整代碼
const STATUS = {
"PENDING": "pending",
"FULFILLED": "fulfilled",
"REJECTED": "rejected"
}
//解析x類型别惦,決定promise2走成功還是失敗
function resolvePromise(promise2, x, resolve, reject) {
if (x == promise2) {
return reject(new TypeError("返回值錯誤,不能使用同一個promise"))
}
//只有object或者function才能是Promise
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
let called = false;//成功或者失敗方法只能調用一次夫椭,防止其他Promise實現錯誤
try {
let then = x.then;//通過判斷x上是否有then函數掸掸,判斷x是否是一個Promise
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
// resolve(y) y有可能還是promise 遞歸解析 直到是普通值為止
resolvePromise(promise2, y, resolve, reject);
}, r => {
if (called) return;
called = true;
reject(r);
})
} else {
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
}
class Promise {
/**
* Creates a new Promise.
*
* @param executor — A callback used to initialize the promise.
* This callback is passed two arguments: a resolve callback used to resolve the promise
* with a value or the result of another promise, and a reject callback used to reject the
* promise with a provided reason or error.
*/
constructor(executor) {
this.status = STATUS.PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.status === STATUS.PENDING) {
this.status = STATUS.FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn());
}
};
const reject = (reason) => {
if (this.status === STATUS.PENDING) {
this.status = STATUS.REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error)
}
}
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled — The callback to execute when the Promise is resolved.
* @param onrejected — The callback to execute when the Promise is rejected.
* @returns — A Promise for the completion of which ever callback is executed.
*/
then(onfulfilled, onrejected) {
//判斷then傳遞的參數是否是函數,如果不是則包裝成一個函數
onfulfilled = typeof onfulfilled === 'function' ? onfulfilled : x => x;
onrejected = typeof onrejected === 'function' ? onrejected : error => {
throw error
};
let promise2 = new Promise((resolve, reject) => {
if (this.status === STATUS.FULFILLED) {
setTimeout(() => { //創(chuàng)建一個宏任務蹭秋,保證promise2已完成創(chuàng)建
try {
let x = onfulfilled(this.value); //x的返回值有可能是一個新的Promise猾漫,需要進行判斷和處理
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error) //如果返回異常,捕獲并作為失敗結果返回
}
// resolve(x)
}, 0);
}
if (this.status === STATUS.REJECTED) {
setTimeout(() => {
try {
let x = onrejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error)
}
// reject(x)
}, 0);
}
if (this.status === STATUS.PENDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onfulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error)
}
}, 0)
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onrejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error)
}
}, 0);
});
}
});
return promise2;
}
catch(errFn) {
return this.then(null, errFn);
}
}
Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
})
return dfd;
}
module.exports = Promise;