摘要:請(qǐng)幫助弗利薩完全變身成第形態(tài),擊敗賽亞人。而弗利薩只要在每次變身成功或者失敗時(shí)發(fā)出通知就行了。讓弗利薩在變身完成或失敗時(shí),通過(guò)這個(gè),告知所有收看該節(jié)目的觀眾他變身失敗,或者成功了。讓弗利薩開(kāi)始變身前往查看示例代碼
這邊文章試圖通過(guò)一個(gè)例子展示javascript異步編程的幾種寫法。示例說(shuō)明
弗利薩必須要從第1形態(tài)過(guò)渡到第8形態(tài)才有可能擊敗賽亞人,每一次變身成下一形態(tài)需要1秒鐘,在這期間他可能會(huì)遭受到賽亞人的攻擊,如果在變身過(guò)程中受到傷害,他將被打回第一形態(tài)。請(qǐng)幫助弗利薩完全變身成第8形態(tài),擊敗賽亞人。
弗利薩的單例對(duì)象開(kāi)始創(chuàng)建一個(gè)弗利薩
const Frieza = (function () { var state = 1; //內(nèi)部變量,表示弗利薩的當(dāng)前形態(tài) return { chargingFlag: false, //表示弗利薩是否正在變身中 damage: function () { //20%幾率收到傷害 return Math.random() < 0.2; }, stateReset: function () { //打回第一形態(tài) state = 1; }, getState: function () { //外部訪問(wèn)state的接口函數(shù) return state; }, change: function (callback) { //變身 if (this.chargingFlag === true) { throw new Error(`弗利薩還沒(méi)變身完畢呢`); } this.chargingFlag = true; console.log(`弗利薩開(kāi)始進(jìn)行第${state + 1}形態(tài)變身`) setTimeout(() => { //每一階段變身消耗1秒 if (this.damage()) { this.stateReset(); this.chargingFlag = false; callback("變身被悟空打斷啦!"); return; } state++; this.chargingFlag = false; callback(null, state); }, 1000) } } })();
以上代碼用立即執(zhí)行函數(shù)創(chuàng)建了一個(gè)弗利薩:
state為內(nèi)部變量,表示弗利薩當(dāng)前的形態(tài),初始為第一形態(tài),并且設(shè)置了一個(gè)接口(getState函數(shù))供外部了解弗利薩當(dāng)前的形態(tài)。
change函數(shù)實(shí)現(xiàn)了弗利薩的變身,必須等到一次變身完畢后才能再次變身,每一次變身需要1秒鐘。
在每一次變身完畢后會(huì)執(zhí)行回調(diào)函數(shù),我們規(guī)定回調(diào)函數(shù)有兩個(gè)參數(shù),第一個(gè)表示變身失敗,被打斷時(shí)應(yīng)當(dāng)傳入的參數(shù),第二個(gè)表示變身成功時(shí)應(yīng)當(dāng)傳入的參數(shù)。
接下來(lái)需要寫一些代碼來(lái)幫助弗利薩鍥而不舍的變身,直到他成功變身到第8形態(tài)。示例最終會(huì)按下圖的樣子在控制臺(tái)中呈現(xiàn)。用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();
看上去已經(jīng)不錯(cuò)了,這已經(jīng)比直接在回調(diào)函數(shù)里面寫回調(diào)函數(shù)要好得多了,我們通過(guò)遞歸調(diào)用handelKeepChange,讓這條Promise鏈持續(xù)到第八次變身完畢。
用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的寫法要復(fù)雜一些,但是因?yàn)槔昧松善鞯奶匦裕沟梦覀冊(cè)趫?zhí)行具體的異步業(yè)務(wù)時(shí),可以寫的比較優(yōu)雅:
function* async() { while (Frieza.getState() !== 8) { yield keepChange(); } console.log("成功!"); }
這種寫法比較有親和力,邏輯上比較清晰。它內(nèi)部的實(shí)現(xiàn)是通過(guò)一個(gè)handleAsync函數(shù)不斷地遞歸調(diào)用handle函數(shù),從而讓生成器能在一次Promis承諾實(shí)現(xiàn)后讓生成器繼續(xù)產(chǎn)出下一次Promise。
function handle(v) { if (!v.done) { // 如果生成器還沒(méi)結(jié)束,那么就繼續(xù)產(chǎn)出一個(gè)promise v.value.then(state => { handle(ita.next(state)); }).catch(err => { console.log(err); handle(ita.next()); }) } }用async await幫助弗利薩
async await是promise+生成器的語(yǔ)法層面實(shí)現(xiàn)。可以讓我們省略背后的細(xì)節(jié),直接采用同步寫法編寫異步程序。
async function handleAsync() { while(Frieza.getState() !== 8){ try { await keepChange(); } catch (error) { console.log(error) } } console.log("成功!"); } handleAsync(); */
這樣就可以了,幾乎與promise+與生成器的業(yè)務(wù)寫法一模一樣。
用rxjs幫助弗利薩用上rxjs的觀察者模式后,實(shí)際上就可以把弗利薩的change函數(shù)里面的callback給解耦出來(lái)。把這部分的邏輯交給觀察者處理里面。而弗利薩只要在每次變身成功或者失敗時(shí)發(fā)出通知就行了。
具體步驟如下:
創(chuàng)建一個(gè)可以供大家收看的電視節(jié)目"dragonBall",這個(gè)被我們叫做七龍珠的電視節(jié)目(subject)可以被觀眾們訂閱,同時(shí),這個(gè)電視節(jié)目也能隨心所欲的播放他想要給觀眾們看到的東西。
const dragonBall = new Rx.Subject();
讓弗利薩在變身完成或失敗時(shí),通過(guò)dragnonBall這個(gè)subject,告知所有收看該節(jié)目的觀眾他變身失敗,或者成功了。修改弗利薩的change函數(shù):
change: function () { if (this.chargingFlag === true) { drangonBall.next(new Error("變身還沒(méi)結(jié)束呢!")) } this.chargingFlag = true; console.log(`弗利薩開(kāi)始進(jìn)行第${state + 1}形態(tài)變身`) setTimeout(() => { if (this.damage()) { this.stateReset(); this.chargingFlag = false; dragonBall.next(new Error("變身被悟空打斷啦!")); return; } state++; this.chargingFlag = false; dragonBall.next(`${state}形態(tài)變身成功!`) }, 1000) }
收看dragonBall,并且在弗利薩沒(méi)變到第8形態(tài)前,持續(xù)地讓弗利薩變身。
const watchAnime = dragonBall.asObservable() .subscribe(message => { console.log(message); if (Frieza.getState() !== 8) { Frieza.change(); } else { watchAnime.unsubscribe(); } })
讓弗利薩開(kāi)始變身
Frieza.change();
前往github查看示例代碼
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/95592.html
摘要:本章將介紹基本的數(shù)據(jù)結(jié)構(gòu)。松鼠人一般在晚上八點(diǎn)到十點(diǎn)之間,雅克就會(huì)變身成為一只毛茸茸的松鼠,尾巴上的毛十分濃密。我們將雅克的日記表示為對(duì)象數(shù)組。 來(lái)源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Data Structures: Objects and Arrays 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 自豪地采用谷歌翻譯 部分參考了《Jav...
摘要:年月日,美國(guó),西雅圖微軟年度開(kāi)發(fā)者盛會(huì)在美國(guó)西雅圖開(kāi)幕,微軟公司首席執(zhí)行官薩提亞納德拉微軟全球執(zhí)行副總裁兼云計(jì)算與企業(yè)事業(yè)部負(fù)責(zé)人微軟全球執(zhí)行副總裁兼人工智能及微軟研究事業(yè)部負(fù)責(zé)人沈向洋,與數(shù)千名來(lái)自全球各地的開(kāi)發(fā)者齊聚一堂。2017年5月10日,美國(guó),西雅圖——微軟年度開(kāi)發(fā)者盛會(huì)Build 2017在美國(guó)西雅圖開(kāi)幕,微軟公司首席執(zhí)行官薩提亞 納德拉、微軟全球執(zhí)行副總裁兼云計(jì)算與企業(yè)事業(yè)部負(fù)...
摘要:瓦工的機(jī)房,電信為雙程線路,可選機(jī)房為洛杉磯弗利蒙新澤西荷蘭這個(gè)機(jī)房,帶寬為口,最低配的月流量為。相比較和價(jià)格相仿,但是配置更高,額外還贈(zèng)送免費(fèi)快照,免費(fèi)自動(dòng)備份等。瓦工的dc2機(jī)房,電信為雙程cn2線路,可選機(jī)房為洛杉磯(QN,MC)/弗利蒙/新澤西/荷蘭這5個(gè)機(jī)房,帶寬為G口,最低配的月流量為1T。相比較和dc3價(jià)格相仿,但是配置更高,額外還贈(zèng)送免費(fèi)快照,免費(fèi)自動(dòng)備份等。 ...
摘要:從最開(kāi)始的到封裝后的都在試圖解決異步編程過(guò)程中的問(wèn)題。為了讓編程更美好,我們就需要引入來(lái)降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁(yè)面加載發(fā)生了什么這是一篇開(kāi)發(fā)的科普類文章,涉及到優(yōu)化等多個(gè)方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進(jìn)的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識(shí)之 HTTP 協(xié)議 詳細(xì)介紹 HTT...
閱讀 3433·2023-04-25 18:14
閱讀 1526·2021-11-24 09:38
閱讀 3244·2021-09-22 14:59
閱讀 3060·2021-08-09 13:43
閱讀 2562·2019-08-30 15:54
閱讀 562·2019-08-30 13:06
閱讀 1540·2019-08-30 12:52
閱讀 2719·2019-08-30 11:13