亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

JavaScript:遞歸函數無法正確處理 Promise

JavaScript:遞歸函數無法正確處理 Promise

四季花海 2023-05-25 17:06:38
我正在用 Node.js 編寫一個簡單的游戲。玩家采取行動,這是作為承諾發出的。接下來檢查移動的合法性:如果合法 - 很好,執行下一個“.then”如果不是 - 遞歸調用相同的函數以獲得新的移動什么有效:我設法使用“reject”+“catch”打破承諾鏈并遞歸調用該函數。什么不起作用:當_makeMove第二次被調用時,它應該要求玩家采取新的行動,暫停直到他們回答。實際發生的是該函數只是運行到第 3 步,而不是等待玩家的進入。我正在通過終端輸入,窗口仍然在“請輸入:”,但代碼已經跑掉了..(最終遇到“未定義”錯誤,這是很自然的,因為玩家還沒有機會輸入新的著法)。代碼(簡化):const _makeMove = (activePlayer) => {    //player makes a move, which is returned as a promise    activePlayer.proposeMove()      //Step 1 - check if legal      .then(proposedMove => {        if (!gameBoard.checkLegal(proposedMove)) {          return Promise.reject("bad entry");        }        return proposedMove;      })      //Step 2 - record the move      .then(proposedMove => {        activePlayer.recordMove(proposedMove);        return proposedMove;      }) //unless step 1 fails...      .catch(err => {        console.log('oops bad entry!')        //in which case let's ask the player to move again...        //by calling the function RECURSIVELY        _makeMove(activePlayer);      })      //Step 3 - game goes on...      .then(proposedMove => {        //more stuff      })  }我完全不解。為什么遞歸調用沒有按預期工作?
查看完整描述

4 回答

?
ABOUTYOU

TA貢獻1812條經驗 獲得超5個贊

為了讓您的承諾鏈從中獲取價值_makeMove,您必須返回的結果_makeMove。不要擔心價值是一個承諾;它將then在調用鏈中的下一個之前自動解析。


      .catch(err => {

        console.log('oops bad entry!')

        return _makeMove(activePlayer);

        //  ^ return here

      })

但是,_makeMove此處的結果將在 返回之前完成then,這可能會使您的recordMove調用返回兩次。您可能需要拆分為_makeMove和_recordMove函數,以便遞歸調用_makeMove不會記錄移動。


雖然理論上您可能會用完堆棧,但對于合理數量的移動嘗試,它不會影響正確性。上面的兩個錯誤會。


查看完整回答
反對 回復 2023-05-25
?
Qyouu

TA貢獻1786條經驗 獲得超11個贊

我不確定你應該在這里使用遞歸調用。如果你得到一個非常垃圾的播放器,你可能會遇到 Stack Overflow 錯誤;)


const _makeMove = async (activePlayer) => {

  let proposedMove = null;


  while (1) {

    proposedMove = await activePlayer.proposeMove();

    if (gameBoard.checkLegal(proposedMove)) {

       break;

    }

  }

  activePlayer.recordMove(proposedMove);

  // do more stuff

}


查看完整回答
反對 回復 2023-05-25
?
收到一只叮咚

TA貢獻1821條經驗 獲得超5個贊

  1. .then使用async/await.?這解決了遞歸調用落到第 3 步而不是在第 2 步暫停的原始問題(我仍然覺得這很神奇......)

  2. 然而,這產生了一個新問題。最初我將一個鏈接.catch到函數的末尾async,但只觸發了一次。即第 2、3、4 次遞歸調用會導致Unhandled exception錯誤。所以我改為將所有代碼放在try函數內的一個塊內,并將一個catch塊也放在函數內。這很好用

查看完整回答
反對 回復 2023-05-25
?
MM們

TA貢獻1886條經驗 獲得超2個贊

const _makeMove = async (activePlayer) => {

    try {

      //Step 1 - take input

      const proposedMove = await activePlayer.proposeMove();


      //Step 2 - check if legal

      if (!gameBoard.checkLegal(proposedMove)) {

        throw new Error("bad entry");

      }


      //Step 3 - etc

      //Step 4 - etc

      //Step 5 - etc


    } catch (e) {

      console.log('oops bad entry!')

      console.log("how it works: type 2 numbers ONLY, each between 1 and 3 (no spaces), to signify your move")

      console.log("eg to place a mark into bottom left corner type 33. First cell = 11. Bang in the center = 22. You get it.")

      console.log('lets try again...')

      return _makeMove(activePlayer);

    }

  };


查看完整回答
反對 回復 2023-05-25
  • 4 回答
  • 0 關注
  • 185 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號