手寫promise

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>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末驶沼,一起剝皮案震驚了整個濱河市炮沐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌回怜,老刑警劉巖大年,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異玉雾,居然都是意外死亡翔试,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門复旬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來垦缅,“玉大人,你說我怎么就攤上這事驹碍”谙眩” “怎么了柏蘑?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長粹庞。 經(jīng)常有香客問我咳焚,道長,這世上最難降的妖魔是什么庞溜? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任革半,我火速辦了婚禮,結(jié)果婚禮上流码,老公的妹妹穿的比我還像新娘又官。我一直安慰自己,他們只是感情好漫试,可當(dāng)我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布六敬。 她就那樣靜靜地躺著,像睡著了一般驾荣。 火紅的嫁衣襯著肌膚如雪外构。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天播掷,我揣著相機與錄音审编,去河邊找鬼。 笑死歧匈,一個胖子當(dāng)著我的面吹牛垒酬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播件炉,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼勘究,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了斟冕?” 一聲冷哼從身側(cè)響起口糕,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎宫静,沒想到半個月后走净,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體券时,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡孤里,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了橘洞。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捌袜。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖炸枣,靈堂內(nèi)的尸體忽然破棺而出虏等,到底是詐尸還是另有隱情弄唧,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布霍衫,位于F島的核電站候引,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏敦跌。R本人自食惡果不足惜澄干,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望柠傍。 院中可真熱鬧麸俘,春花似錦、人聲如沸惧笛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽患整。三九已至拜效,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間各谚,已是汗流浹背拂檩。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嘲碧,地道東北人稻励。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像愈涩,于是被迫代替她去往敵國和親望抽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容