promise是什么?
1缠劝、主要用于異步計算
2潮梯、可以將異步操作隊列化,按照期望的順序執(zhí)行惨恭,返回符合預(yù)期的結(jié)果
3秉馏、可以在對象之間傳遞和操作promise,幫助我們處理隊列
promise是一個對象脱羡,對象和函數(shù)的區(qū)別就是對象可以保存狀態(tài)萝究,函數(shù)不可以(閉包除外)
并未剝奪函數(shù)return的能力,因此無需層層傳遞callback锉罐,進(jìn)行回調(diào)獲取數(shù)據(jù)
代碼風(fēng)格帆竹,容易理解,便于維護(hù)
多個異步等待合并便于解決
使用介紹
new Promise(
function (resolve, reject) {
// 一段耗時的異步操作
resolve('成功') // 數(shù)據(jù)處理完成
// reject('失敗') // 數(shù)據(jù)處理出錯
}
).then(
(res) => {console.log(res)}, // 成功
(err) => {console.log(err)} // 失敗
resolve作用是脓规,將Promise對象的狀態(tài)從“未完成”變?yōu)椤俺晒Α保磸?pending 變?yōu)?resolved)栽连,在異步操作成功時調(diào)用,并將異步操作的結(jié)果抖拦,作為參數(shù)傳遞出去升酣;
reject作用是舷暮,將Promise對象的狀態(tài)從“未完成”變?yōu)椤笆 保磸?pending 變?yōu)?rejected)态罪,在異步操作失敗時調(diào)用,并將異步操作報出的錯誤下面,作為參數(shù)傳遞出去复颈。
promise有三個狀態(tài):
1、pending[待定]初始狀態(tài)
2沥割、fulfilled[實現(xiàn)]操作成功
3耗啦、rejected[被否決]操作失敗
當(dāng)promise狀態(tài)發(fā)生改變,就會觸發(fā)then()里的響應(yīng)函數(shù)處理后續(xù)步驟机杜;
promise狀態(tài)一經(jīng)改變帜讲,不會再變。
Promise對象的狀態(tài)改變椒拗,只有兩種可能:
從pending變?yōu)閒ulfilled
從pending變?yōu)閞ejected似将。
這兩種情況只要發(fā)生获黔,狀態(tài)就凝固了,不會再變了在验。
1 JS
class KPromise {
// handle => function (resolve, reject) {
// // 一段耗時的異步操作
// resolve('成功') // 數(shù)據(jù)處理完成
// // reject('失敗') // 數(shù)據(jù)處理出錯
// }
constructor(handle) {
this.status = "pending";
this.value = undefined;
this.resolvedQueue = [];
this.rejectedQueue = [];
handle(this._resolve.bind(this), this._reject.bind(this));
}
_resolve(val) {
// console.log(this);
// 改變狀態(tài)及value
this.status = "resolved";
this.value = val;
// console.log(val);
// 執(zhí)行then里成功成功的回調(diào)
// console.log(this.resolvedQueue.length);
let run = ()=>{
let cb;
while(cb=this.resolvedQueue.shift()){
cb(val);
}
}
// setTimeout(run, 0);
let observer = new MutationObserver(run)
observer.observe(document.body,{
attributes: true
})
document.body.setAttribute("kkb",Math.random());
}
_reject(err) {
this.status = "rejected";
this.value = err;
// console.log(err);
// 執(zhí)行then里失敗的回調(diào)玷氏;
let run = ()=>{
let cb;
while(cb=this.rejectedQueue.shift()){
cb(err);
}
}
// setTimeout(run, 0);
// 模擬微任務(wù);
let observer = new MutationObserver(run)
observer.observe(document.body,{
attributes: true
})
document.body.setAttribute("kkb",Math.random());
}
then(onResolved, onRejected) {
// 把多個 onResolved 及 onRejected 放在隊列里腋舌;
// if (this.status === "resolved") {
// onResolved(this.value);
// } else if (this.status === 'rejected') {
// onRejected(this.value);
// }
// 加入隊列盏触, 沒有執(zhí)行;
// this.resolvedQueue.push(onResolved);
// this.rejectedQueue.push(onRejected);
// 返還KPromise對象块饺;
return new KPromise((resolve,reject)=>{
// 在then里執(zhí)行的回調(diào)
// let res = onResolved()
this.resolvedQueue.push(val=>{
val = onResolved && onResolved(val)
// val 111 赞辩、new KPromise();
if(val instanceof KPromise){
// console.log("promise...",val)
// 返還的KPromise對象;
return val.then(resolve);
}
// 返還的普通值授艰;
resolve(val);
})
this.rejectedQueue.push(err=>{
onRejected && onRejected(err);
reject(err);
})
// if(res instanceof KPromise){
// console.log("then返還的是KPromise對象那個 ");
// }
// resolve(res);
})
}
static resolve(val){
return new KPromise(resolve=>{
resolve(val);
})
}
static reject(val){
return new KPromise((resolve,reject)=>{
reject(val);
})
}
static all(lists){
return new KPromise((resolve,reject)=>{
let arr = [];
for(let i=0;i<lists.length;i++){
lists[i].then(res=>{
arr.push(res);
},err=>{
reject(err);
throw Error("error..")
})
}
resolve(arr);
})
}
static race(lists){
return new KPromise((resolve,reject)=>{
for(let i=0;i<lists.length;i++){
lists[i].then(res=>{
resolve(res)
},err=>{
reject(err);
})
}
})
}
catch(onRejected){
this.then(undefined,onRejected);
}
}
promise.allSettled()
方法接受一組 Promise 實例作為參數(shù)诗宣,包裝成一個新的 Promise 實例。
只有等到所有這些參數(shù)實例都返回結(jié)果想诅,不管是fulfilled還是rejected召庞,包裝實例才會結(jié)束。
每個成員對應(yīng)一個傳入Promise.allSettled()的 Promise 實例 ,一旦結(jié)束来破,狀態(tài)總是fulfilled篮灼,不會變成rejected
使用eg:
const resolved = Promise.resolve(42);
const rejected = Promise.reject(-1);
const allSettledPromise = Promise.allSettled([resolved, rejected]);
allSettledPromise.then(function (results) {
console.log(results);
});
// [
// { status: 'fulfilled', value: 42 },
// { status: 'rejected', reason: -1 }
// ]
static allSettled(lists){
return new KPromise((resolve,reject)=>{
let arr = [];
for(let i=0;i<lists.length;i++){
lists[i].then(res=>{
arr.push(res);
})
}
resolve(arr);
})
}
1 html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./myPromise.js"></script>
</head>
<body>
<h1>自己封裝的promise</h1>
</body>
<script>
// setTimeout(() => {
// console.log("settimeout....");
// }, 0);
// let p = new KPromise((resolve,reject)=>{
// // resolve();
// // 執(zhí)行了回調(diào)
// // setTimeout(() => {
// // resolve("success");
// // }, 100);
// reject("err");
// })
// console.log(p);
// then 加入隊列 ;先執(zhí)行 后加入了徘禁; --->先加入隊列诅诱,后執(zhí)行;
// let res = p.then(res=>{
// console.log(res);
// // console.log(res);
// // return KPromise
// // return 111;
// // return new KPromise(resolve=>{
// // resolve("返還的KPromise");
// // })
// },err=>{
// console.log(err);
// })
// console.log("??",res);
// then始終返還的promise對象送朱;--->鏈?zhǔn)秸{(diào)用娘荡;
// res.then(res=>{
// console.log(res);
// })
// let p = KPromise.reject("111");
// console.log(p);
// let p = new KPromise((resolve,reject)=>{
// reject("err...");
// })
// p.then(res=>{
// console.log(res);
// }).catch(err=>{
// console.log(err);
// })
// let p1 = new KPromise((resolve,reject)=>{
// // resolve(111);
// reject("err...")
// })
// let p2 = new KPromise(resolve=>{
// resolve(222);
// })
// KPromise.all([p1,p2]).then(res=>{
// console.log(res);
// })
let p1 = new KPromise(resolve=>{
setTimeout(() => {
resolve(111);
}, 1000);
})
let p2 = new KPromise(resolve=>{
setTimeout(() => {
resolve(222);
}, 2000);
})
// 所有結(jié)果都必須是resolve;
// Promise.all([p1,p2]).then(res=>{
// console.log(res);
// })
KPromise.race([p1,p2]).then(res=>{
console.log(res);
})
</script>
</html>