基于Node.js Events与ES6模块化实现自定义状态管理器的问题
嘿,我看你已经自己找到了解决的核心思路——把StateManager实例传递给Loader,不过咱们再理清楚之前出错的原因,以及优化后的代码细节:
你之前碰到的Cannot read property 'emit' of undefined错误,核心问题有两个:
- 静态方法拿不到实例属性:
Manager里的loadedImages是静态方法,它属于类本身,根本访问不到实例的this.state对象,自然会报错。 - 图片加载的异步逻辑没处理对:原来的
load方法里直接判断this.loadCount === this.imageCount,但图片加载是异步操作,这行代码会在所有图片开始加载前就执行,根本等不到加载完成的时机。
下面是完善后的代码,还有几个关键优化点:
修改后的Loader.js
'use strict'; import Manager from './Manager'; const DIRECTORY = 'assets/img/'; const IMG = { BACKGROUND_01: 'background_01.jpg', PLAYER_01: 'player_01.png', KEEPER_01: 'keeper_01.png' } export default class Loader { constructor() { } setup(state) { this.state = state; this.load(); } load() { this.imageCount = Object.values(IMG).length; // 直接取图片总数,避免手动累加出错 this.loadCount = 0; Object.values(IMG).forEach(img => this.loadImage(img)); // 遍历加载所有图片 } loadImage(image) { let img = new Image(); img.src = DIRECTORY + image; // 用箭头函数保证this指向Loader实例 img.onload = () => { this.loadCount++; console.log('Loaded: ' + image); // 每次加载完成后检查是否全部加载完毕 if (this.loadCount === this.imageCount) { console.log('Loaded images!'); this.state.setState('loaded'); } }; // 新增加载失败处理,避免某张图加载失败导致永远无法触发状态变更 img.onerror = () => { console.error('Failed to load: ' + image); this.loadCount++; // 即使加载失败,也检查是否所有任务都完成 if (this.loadCount === this.imageCount) { console.log('All image load tasks finished (some failed)'); this.state.setState('loaded'); } }; } }
修改后的Manager.js
'use strict'; import { EventEmitter } from 'events'; // 修正EventEmitter的导入方式 import Canvas from './Canvas'; import Loader from './Loader'; class StateManager extends EventEmitter { constructor () { super(); this.currentState = ''; } setState(id) { this.currentState = id; console.log(`Current state: ${this.currentState}`); this.emit(id); } } export default class Manager { constructor() { this.init(); } init() { this.state = new StateManager(); // 绑定this到changeState,避免回调时this指向错误 this.state.on('loaded', this.changeState.bind(this)); this.Canvas = new Canvas(); this.Loader = new Loader(); this.Loader.setup(this.state); } changeState() { console.log('Loaded all content! Lets go!'); } }
关键优化说明
- 修复异步判断逻辑:把加载完成的检查放到
img.onload回调里,每次图片加载完成后都判断是否全部加载完毕,确保触发状态变更的时机正确。 - 正确绑定this:用箭头函数或
bind保证回调中的this指向正确的实例,避免出现属性找不到的问题。 - 简化图片数量统计:用
Object.values(IMG).length直接获取图片总数,减少手动累加的出错概率。 - 添加错误处理:新增
img.onerror回调,避免某张图片加载失败导致永远无法触发loaded事件。 - 修正EventEmitter导入:原来的导入方式错误,改为从
events模块正确导入EventEmitter类。
内容的提问来源于stack exchange,提问作者TkyStm
相关产品推荐
相关产品推荐

