Phaser.js场景切换时Axios请求时序问题求解
解决Phaser 3中Axios请求后加载场景的时序问题
核心问题
你遇到的问题根源是:Phaser游戏配置中声明的所有场景会被自动初始化,哪怕你没手动调用scene.start。所以GameScene的init方法会在Axios异步请求完成前就执行,自然拿不到返回的数据。
方案1:动态注册GameScene(推荐)
不在游戏配置里提前注册GameScene,等Axios请求成功后再动态注册并启动它,从根源避免时序冲突。
修改SelectDifficultyScene.js的代码:
preload() { this.fetchSudoku(); } async fetchSudoku() { console.log("Select Difficulty Scene"); try { const response = await axios.get('api/fetch-sudoku'); this.setSudoku(response.data); // 动态注册并启动GameScene,第三个参数true表示立即启动 this.scene.add('GameScene', GameScene, true, this.sudoku); } catch(error) { console.log(error); } } setSudoku(sudoku) { // 先初始化sudoku对象,避免undefined报错 this.sudoku = { unsolvedSudoku: sudoku.unsolvedSudoku, solvedSudoku: sudoku.solvedSudoku, difficultyLevel: "Easy" }; }
游戏配置中只保留SelectDifficultyScene:
const config = { type: Phaser.AUTO, width: 800, height: 600, // 仅注册初始场景 scene: [SelectDifficultyScene] // 其他配置项... };
方案2:让GameScene等待数据就绪
如果必须在配置里注册GameScene,可以给GameScene添加事件监听,等待数据就绪后再处理:
修改GameScene.js的代码:
init(sudoku) { // 如果初始化时没有拿到数据,监听自定义事件等待数据 if (!sudoku) { this.events.on('sudoku-ready', (data) => { this.setSudokuNumbers(data); }); return; } // 拿到数据直接处理 this.setSudokuNumbers(sudoku); } setSudokuNumbers(sudoku) { let count = 0; // 合并重复的计数变量,简化代码 for(let x = 0; x < 9; x++) { for(let y = 0; y < 9; y++) { this.sudokuGridUnsolved[x][y] = sudoku.unsolvedSudoku[count]; this.sudokuGridSolved[x][y] = sudoku.solvedSudoku[count]; count++; } } }
修改SelectDifficultyScene.js的loadGameScene方法:
loadGameScene() { const gameScene = this.scene.get('GameScene'); if (gameScene) { // 触发自定义事件传递数据 gameScene.events.emit('sudoku-ready', this.sudoku); } else { this.scene.start('GameScene', this.sudoku); } }
额外修复点
- 原代码中
setSudoku方法直接给this.sudoku赋值属性,但如果this.sudoku未提前初始化会报错,方案1中已通过直接创建对象解决。 - 原
fetchSudoku里的self = this存在全局作用域污染风险,直接使用this即可(async函数中this指向当前场景实例)。
内容的提问来源于stack exchange,提问作者summer9844
相关产品推荐
相关产品推荐

