摘要:可以利用這點(diǎn)做定時(shí)器的清理工作,而且可以說(shuō)基本不會(huì)忘記可以將后面的變量可迭代的變量,字符串?dāng)?shù)組等中的值一個(gè)一個(gè)的返回。執(zhí)行一次返回其中的一個(gè)值函數(shù)完美實(shí)現(xiàn)流程圖代碼部分其他變量下注下注階段完成后直接清除定時(shí)器。
扯蛋
做了兩年的Nodejs全棧開(kāi)發(fā),不知道為什么跑來(lái)做游戲呢(大概是廈門(mén)nodejs不好找工作吧)。用的是網(wǎng)易的pomelo的游戲框架?,F(xiàn)接手了一個(gè)棋牌游戲:二十一點(diǎn),不懂的規(guī)則的可以自行百度。
接手了平臺(tái)其他相關(guān)游戲的代碼,流程控制相互交錯(cuò),不易理解、難以維護(hù)。(可能是剛做游戲的原因,如果你們有什么更簡(jiǎn)單的流程控制方法,歡迎分享)。我下意識(shí)的就想到了Generator函數(shù)的特性,感覺(jué)用著這里非常方便(以前一直覺(jué)得這是個(gè)異步流程控制中過(guò)度性質(zhì)的方法,并且需要配合co才能自動(dòng)執(zhí)行,所以基本沒(méi)實(shí)際用過(guò),koa不算...)
Js Generator函數(shù)實(shí)現(xiàn)流程控制的優(yōu)點(diǎn)1、易于理解、便于開(kāi)發(fā)、容易維護(hù)(看到Generator函數(shù)猶如看到了流程圖)
2、開(kāi)發(fā)思路清晰(每個(gè)階段(函數(shù))只需要關(guān)注自己的業(yè)務(wù)邏輯,完成直接下一步,而不用管下一步要做什么操作)
3、不存在會(huì)忘記清除定時(shí)器的問(wèn)題
1、Generator函數(shù)執(zhí)行后會(huì)生成一個(gè)Iterator。(注意不要加new)(簡(jiǎn)單說(shuō)就是個(gè)有next方法的對(duì)象,執(zhí)行一次返回一個(gè)值)
2、每次next的調(diào)用,執(zhí)行yield后面的語(yǔ)句并返回該語(yǔ)句執(zhí)行的結(jié)果
3、每次只執(zhí)行一個(gè)yield,后面的語(yǔ)句不會(huì)再執(zhí)行、只有在執(zhí)行下次next函數(shù)時(shí)才執(zhí)行。(可以利用這點(diǎn)做定時(shí)器的清理工作,而且可以說(shuō)基本不會(huì)忘記)
4、yield* 可以將后面的變量(可迭代的變量,字符串、數(shù)組等)中的值一個(gè)一個(gè)的返回。執(zhí)行一次返回其中的一個(gè)值
class EsydProcess { constructor(room) { /** * ...其他變量 */ this.flow = this.flowGenerator(); } *["flowGenerator"]() { yield this.betStage(); // 下注 this.betStageTimer && clearTimeout(this.betStageTimer);// 下注階段完成后直接清除定時(shí)器。完全不用擔(dān)心定時(shí)器沒(méi)有被清理的情況 yield this.assignStage(); // 分牌 if (this.esydCard.getCardPoint(this.bankerCards[0]) === 1) { yield this.ensureStage(); // 保險(xiǎn) this.ensureStageTimer && clearTimeout(this.ensureStageTimer); if (this.esydCard.getCardType(this.bankerCards) !== CardTypes.BLACK_JACK) { yield* this.operateStage(); // 操作 } } else { yield* this.operateStage(); // 操作 } yield this.settleStage(); // 結(jié)算 } *["operateStage"]() { // 通知進(jìn)入玩家操作階段 this.noticeChangeStage(esydConsts.gameStage.OPERATE_STAGE); let players = this.players; for (let uid in players) { let player = players[uid]; // 操作第一副牌 yield this.changeOperatingPlayer(player); player.getCurCardInfo().isStop = true; this.operateTimer && clearTimeout(this.operateTimer); if (player.isSperated) { // 如果有一副牌,操作第二副牌 player.curCardsIndex = 1; yield this.changeOperatingPlayer(player); player.getCurCardInfo().isStop = true; this.operateTimer && clearTimeout(this.operateTimer); } } yield this.bankerOperate(); // 莊家操作 } // 轉(zhuǎn)到下個(gè)階段 nextStage() { process.nextTick(() => { this.flow.next(); }); } // 開(kāi)始游戲 start(seats) { /** * ... * */ // 第一次next,直接進(jìn)入下注階段。整個(gè)流程走完游戲結(jié)束 this.nextStage(); } betStage(){ // 進(jìn)入下注階段 this.noticeChangeStage(esydConsts.gameStage.BET_STAGE); /** * 其他操作 */ this.betStageTimer = setTimeout(() => { this.betStageTimer = null; // 超時(shí),直接進(jìn)入下一步。沒(méi)有下注的玩家使用默認(rèn)底注 this.nextStage(); }, esydConsts.stageTime.BET_STAGE); } assignStage(){ /** * ... * 分牌操作,完成直接下一步 */ this.nextStage(); } ensureStage(){ /** * ... * 各種操作,如通知客戶端、開(kāi)始超時(shí)定時(shí)器等。操作完后直接下一步就Ok了。只需要專(zhuān)注當(dāng)前函數(shù)的功能,完成直接下一步 */ this.nextStage(); } // 監(jiān)聽(tīng)用戶下注操作 userBetOperateListener(uid){ /** * ... * 檢查是否在下注階段,不是不能下注、記錄每個(gè)玩家下注等 */ // 記錄已下注的玩家 this.betedPlayers[uid] = true; if (Object.keys(this.betedPlayers).length === this.seatCount) { // 如果所有玩家都押注完畢, this.nextStage(); } } /** * 其他函數(shù)... */ }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/99568.html
摘要:而在中是迭代器生成器,被創(chuàng)造性的拿來(lái)做異步流程控制了。當(dāng)執(zhí)行的時(shí)候,并不執(zhí)行函數(shù)體,而是返回一個(gè)迭代器。行代碼再看看文章開(kāi)頭的行代碼首先生成一個(gè)迭代器,然后執(zhí)行一遍,得到的是一個(gè)對(duì)象,里面再執(zhí)行。 廣告招人:阿里巴巴招前端,在這里你可以享受大公司的福利和技術(shù)體系,也有小團(tuán)隊(duì)的挑戰(zhàn)和成長(zhǎng)空間。聯(lián)系: qingguang.meiqg at alibaba-inc.com 首先請(qǐng)?jiān)徫业臉?biāo)題...
摘要:以下展示它是如何工作的函數(shù)使用構(gòu)造函數(shù)創(chuàng)建一個(gè)新的對(duì)象,并立即將其返回給調(diào)用者。在傳遞給構(gòu)造函數(shù)的函數(shù)中,我們確保傳遞給,這是一個(gè)特殊的回調(diào)函數(shù)。 本系列文章為《Node.js Design Patterns Second Edition》的原文翻譯和讀書(shū)筆記,在GitHub連載更新,同步翻譯版鏈接。 歡迎關(guān)注我的專(zhuān)欄,之后的博文將在專(zhuān)欄同步: Encounter的掘金專(zhuān)欄 知乎專(zhuān)欄...
摘要:需要說(shuō)明的是,每次執(zhí)行完函數(shù)之后,都會(huì)返回一個(gè)對(duì)象這個(gè)返回值有兩個(gè)屬性和,對(duì)象通過(guò)這個(gè)返回值來(lái)告訴外界函數(shù)的執(zhí)行情況。函數(shù)的返回值變成這樣可以發(fā)現(xiàn)的值變?yōu)榱?,因?yàn)楹瘮?shù)已經(jīng)執(zhí)行完了。在規(guī)范中,新增了兩個(gè)協(xié)議可迭代協(xié)議和迭代器協(xié)議。 Koa是最近比較火的一款基于Node的web開(kāi)發(fā)框架。說(shuō)他是一個(gè)框架,其實(shí)他更像是一個(gè)函數(shù)庫(kù),通過(guò)某種思想(或者說(shuō)某種約定),將眾多的中間件聯(lián)系在一起,從而提...
摘要:換句話說(shuō),我們很好的對(duì)代碼的功能關(guān)注點(diǎn)進(jìn)行了分離通過(guò)將使用消費(fèi)值得地方函數(shù)中的邏輯和通過(guò)異步流程來(lái)獲取值迭代器的方法進(jìn)行了有效的分離。但是現(xiàn)在我們通過(guò)來(lái)管理代碼的異步流程部分,我們解決了回調(diào)函數(shù)所帶來(lái)的反轉(zhuǎn)控制等問(wèn)題。 本文翻譯自 Going Async With ES6 Generators 由于個(gè)人能力知識(shí)有限,翻譯過(guò)程中難免有紕漏和錯(cuò)誤,還望指正Issue ES6 Gener...
摘要:關(guān)于協(xié)程和中的什么是協(xié)程進(jìn)程和線程眾所周知,進(jìn)程和線程都是一個(gè)時(shí)間段的描述,是工作時(shí)間段的描述,不過(guò)是顆粒大小不同,進(jìn)程是資源分配的最小單位,線程是調(diào)度的最小單位。子程序就是協(xié)程的一種特例。 關(guān)于協(xié)程和 ES6 中的 Generator 什么是協(xié)程? 進(jìn)程和線程 眾所周知,進(jìn)程和線程都是一個(gè)時(shí)間段的描述,是CPU工作時(shí)間段的描述,不過(guò)是顆粒大小不同,進(jìn)程是 CPU 資源分配的最小單位,...
閱讀 2668·2021-11-25 09:43
閱讀 1921·2021-09-22 15:26
閱讀 3953·2019-08-30 15:56
閱讀 1788·2019-08-30 15:55
閱讀 1957·2019-08-30 15:54
閱讀 872·2019-08-30 15:52
閱讀 3230·2019-08-29 16:23
閱讀 965·2019-08-29 12:43