封装YouTube API类导入后,调用getPlayerState()提示非函数问题
问题排查与修复方案
核心问题梳理
- 缺失
getPlayerState()方法:你提到调用该方法,但提供的YouTubeManager类中完全没有定义这个方法——console.log看到的方法大概率是YT.Player实例的原生方法,而非你封装类的方法。 playerState属性未正确赋值:onPlayerStateChange里误用了全局变量State,而非类实例的this.playerState,导致该属性始终是初始的null,访问自然报错。- 模块导入导出不兼容:你用ES6的
export default导出实例,但调用方用AMD的define语法导入,两种模块规范不匹配可能导致实例解析异常。
分步修复
1. 添加getPlayerState()方法
在YouTubeManager类中补充该方法,可选择返回类维护的状态,或直接调用YT播放器的原生方法:
class YouTubeManager { // ...其他代码 // 新增方法:返回类维护的playerState getPlayerState() { return this.playerState; // 若要直接调用播放器原生方法,可改为: // return this.player?.getPlayerState(); } // ...其他代码 }
2. 修复playerState赋值逻辑
修改onPlayerStateChange方法,将状态赋值给实例属性,同时用YT常量替代魔法数字提升可读性:
onPlayerStateChange(event) { this.playerState = event.data; // 正确赋值给类实例属性 // eslint-disable-next-line no-undef if (event.data === YT.PlayerState.PLAYING) { console.log("video is playing"); } else if (event.data === YT.PlayerState.PAUSED) { // 用常量代替数字2 console.log("video is paused"); } }
3. 统一模块导入导出规范
由于调用方使用AMD的define,需将导出改为AMD规范:
// 替换原ES6导出代码 define(function() { class YouTubeManager { // 类完整代码不变 } const youtubeManager = new YouTubeManager(); return youtubeManager; });
如果项目支持ES6模块,也可将调用方改为ES6导入:
import $ from 'jquery'; import youtubeManager from './youTubeManager'; youtubeManager.readyPromise.then(() => { console.log(youtubeManager.getPlayerState()); console.log(youtubeManager.playerState); }).catch(error => { console.error(error.message); });
4. 确保播放器完全初始化后再操作
原readyPromise在API加载完成后就resolve,但此时播放器可能还未就绪,建议将resolve移到播放器的onReady事件中:
initYouTubeAPI() { return new Promise((resolve, reject) => { window.onYouTubeIframeAPIReady = () => { this.createPlayer(resolve); // 将resolve传递给createPlayer }; const tag = document.createElement('script'); tag.src = 'https://www.youtube.com/iframe_api'; tag.onerror = () => reject(Error('Error loading YouTube API')); document.getElementsByTagName('head')[0].appendChild(tag); }); } createPlayer(resolve) { // eslint-disable-next-line no-undef this.player = new YT.Player('another-love', { events: { 'onReady': resolve, // 播放器就绪后再resolve 'onStateChange': this.onPlayerStateChange.bind(this) } }); }
内容的提问来源于stack exchange,提问作者Rohit -
相关产品推荐
相关产品推荐

