国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript異步編程:幫助弗利薩完成8次變身

avwu / 1520人閱讀

摘要:請幫助弗利薩完全變身成第形態,擊敗賽亞人。而弗利薩只要在每次變身成功或者失敗時發出通知就行了。讓弗利薩在變身完成或失敗時,通過這個,告知所有收看該節目的觀眾他變身失敗,或者成功了。讓弗利薩開始變身前往查看示例代碼

這邊文章試圖通過一個例子展示javascript異步編程的幾種寫法。
示例說明

弗利薩必須要從第1形態過渡到第8形態才有可能擊敗賽亞人,每一次變身成下一形態需要1秒鐘,在這期間他可能會遭受到賽亞人的攻擊,如果在變身過程中受到傷害,他將被打回第一形態。請幫助弗利薩完全變身成第8形態,擊敗賽亞人。

弗利薩的單例對象

開始創建一個弗利薩

 const Frieza = (function () {
            var state = 1; //內部變量,表示弗利薩的當前形態
            return {
                chargingFlag: false, //表示弗利薩是否正在變身中
                damage: function () {  //20%幾率收到傷害
                    return Math.random() < 0.2;
                },
                stateReset: function () { //打回第一形態
                    state = 1;
                },
                getState: function () { //外部訪問state的接口函數
                    return state;
                },
                change: function (callback) { //變身

                    if (this.chargingFlag === true) { 
                        throw new Error(`弗利薩還沒變身完畢呢`);
                    }
                    this.chargingFlag = true;
                    console.log(`弗利薩開始進行第${state + 1}形態變身`)
                    setTimeout(() => { //每一階段變身消耗1秒
                        if (this.damage()) {
                            this.stateReset();
                            this.chargingFlag = false;
                            callback("變身被悟空打斷啦!");
                            return;
                        }
                        state++;
                        this.chargingFlag = false;
                        callback(null, state);
                    }, 1000)
                }

            }
        })();

以上代碼用立即執行函數創建了一個弗利薩

state為內部變量,表示弗利薩當前的形態,初始為第一形態,并且設置了一個接口(getState函數)供外部了解弗利薩當前的形態。

change函數實現了弗利薩的變身,必須等到一次變身完畢后才能再次變身,每一次變身需要1秒鐘。

在每一次變身完畢后會執行回調函數,我們規定回調函數有兩個參數,第一個表示變身失敗,被打斷時應當傳入的參數,第二個表示變身成功時應當傳入的參數。

接下來需要寫一些代碼來幫助弗利薩鍥而不舍的變身,直到他成功變身到第8形態。示例最終會按下圖的樣子在控制臺中呈現。

用Promise幫助弗利薩:
        function keepChange() {
            return new Promise((resolve, reject) => {
                Frieza.change((err, state) => {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(state);
                    }
                })
            })
        }
        function handelKeepChange() {
            keepChange().then((x) => {
             if(x !== 8){
                handelKeepChange();
             } else {
                 console.log("成功!")
             }
        }).catch(err => {
            console.log(err);
            handelKeepChange();
        })
        }
       handelKeepChange();

看上去已經不錯了,這已經比直接在回調函數里面寫回調函數要好得多了,我們通過遞歸調用handelKeepChange,讓這條Promise鏈持續到第八次變身完畢。

用Promise + 生成器幫助弗利薩
 // generator + promise

        function* async() {
            while (Frieza.getState() !== 8) {
                yield keepChange();
            }
            console.log("成功!");
        }
        function keepChange() {
            return new Promise((resolve, reject) => {
                Frieza.change((err, state) => {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(state);
                    }
                })
            })
        }
        function handleAsync(asyncFn) {
            const ita = asyncFn();
            function handle(v) {
                if (!v.done) {
                    v.value.then(state => {
                        handle(ita.next(state));
                    }).catch(err => {
                        console.log(err);
                        handle(ita.next());
                    })
                }
            }
            handle(ita.next());
        }
        handleAsync(async);

 

這種用生成器+promise的寫法比純用promise的寫法要復雜一些,但是因為利用了生成器的特性,使得我們在執行具體的異步業務時,可以寫的比較優雅:

        function* async() {
            while (Frieza.getState() !== 8) {
                yield keepChange();
            }
            console.log("成功!");
        }

這種寫法比較有親和力,邏輯上比較清晰。它內部的實現是通過一個handleAsync函數不斷地遞歸調用handle函數,從而讓生成器能在一次Promis承諾實現后讓生成器繼續產出下一次Promise。

            function handle(v) {
                if (!v.done) { // 如果生成器還沒結束,那么就繼續產出一個promise
                    v.value.then(state => {
                        handle(ita.next(state));
                    }).catch(err => {
                        console.log(err);
                        handle(ita.next());
                    })
                }
            }
用async await幫助弗利薩

async await是promise+生成器的語法層面實現。可以讓我們省略背后的細節,直接采用同步寫法編寫異步程序。

        async function handleAsync() {
            while(Frieza.getState() !== 8){
                try {
                    await keepChange();
                } catch (error) {
                    console.log(error)
                }
            }
            console.log("成功!");
           
        } 
        handleAsync(); */

這樣就可以了,幾乎與promise+與生成器的業務寫法一模一樣。

用rxjs幫助弗利薩

用上rxjs的觀察者模式后,實際上就可以把弗利薩的change函數里面的callback給解耦出來。把這部分的邏輯交給觀察者處理里面。而弗利薩只要在每次變身成功或者失敗時發出通知就行了。
具體步驟如下

創建一個可以供大家收看的電視節目"dragonBall",這個被我們叫做七龍珠的電視節目(subject)可以被觀眾們訂閱,同時,這個電視節目也能隨心所欲的播放他想要給觀眾們看到的東西。

const dragonBall = new Rx.Subject();

讓弗利薩在變身完成或失敗時,通過dragnonBall這個subject,告知所有收看該節目的觀眾他變身失敗,或者成功了。修改弗利薩的change函數:

            change: function () {

                if (this.chargingFlag === true) {
                    drangonBall.next(new Error("變身還沒結束呢!"))
                }
                this.chargingFlag = true;
                console.log(`弗利薩開始進行第${state + 1}形態變身`)
                setTimeout(() => {
                    if (this.damage()) {
                        this.stateReset();
                        this.chargingFlag = false;
                        dragonBall.next(new Error("變身被悟空打斷啦!"));
                        return;
                    }
                    state++;
                    this.chargingFlag = false;
                    dragonBall.next(`${state}形態變身成功!`)
                }, 1000)
            }

收看dragonBall,并且在弗利薩沒變到第8形態前,持續地讓弗利薩變身。

        const watchAnime = dragonBall.asObservable()
        
        .subscribe(message => {
            console.log(message);
            
            if (Frieza.getState() !== 8) {
                Frieza.change();
            } else {
                watchAnime.unsubscribe();
            }

        })

讓弗利薩開始變身

   Frieza.change();

前往github查看示例代碼

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/95592.html

相關文章

  • JavaScript 編程精解 中文第三版 四、數據結構:對象和數組

    摘要:本章將介紹基本的數據結構。松鼠人一般在晚上八點到十點之間,雅克就會變身成為一只毛茸茸的松鼠,尾巴上的毛十分濃密。我們將雅克的日記表示為對象數組。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Data Structures: Objects and Arrays 譯者:飛龍 協議:CC BY-NC-SA 4.0 自豪地采用谷歌翻譯 部分參考了《Jav...

    kamushin233 評論0 收藏0
  • 從云計算到邊緣計算 打造更智能的未來

    摘要:年月日,美國,西雅圖微軟年度開發者盛會在美國西雅圖開幕,微軟公司首席執行官薩提亞納德拉微軟全球執行副總裁兼云計算與企業事業部負責人微軟全球執行副總裁兼人工智能及微軟研究事業部負責人沈向洋,與數千名來自全球各地的開發者齊聚一堂。2017年5月10日,美國,西雅圖——微軟年度開發者盛會Build 2017在美國西雅圖開幕,微軟公司首席執行官薩提亞 納德拉、微軟全球執行副總裁兼云計算與企業事業部負...

    oneasp 評論0 收藏0
  • 搬瓦工,DC2(QN)機房CN2 VPS測評,可選機房洛杉磯(QN,MC)/弗利蒙/新澤西/荷蘭

    摘要:瓦工的機房,電信為雙程線路,可選機房為洛杉磯弗利蒙新澤西荷蘭這個機房,帶寬為口,最低配的月流量為。相比較和價格相仿,但是配置更高,額外還贈送免費快照,免費自動備份等。瓦工的dc2機房,電信為雙程cn2線路,可選機房為洛杉磯(QN,MC)/弗利蒙/新澤西/荷蘭這5個機房,帶寬為G口,最低配的月流量為1T。相比較和dc3價格相仿,但是配置更高,額外還贈送免費快照,免費自動備份等。 ...

    miguel.jiang 評論0 收藏0
  • JS筆記

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。異步編程入門的全稱是前端經典面試題從輸入到頁面加載發生了什么這是一篇開發的科普類文章,涉及到優化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結思考,循序漸進的理解 TypeScript。 網絡基礎知識之 HTTP 協議 詳細介紹 HTT...

    rottengeek 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<