微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

onYouTubeIframeAPIReady没有在angular2 web应用程序上触发

我正在使用angular 2,typescript和YouTube API构建一个Web应用程序,以便在用户登录后将播放器添加页面中.

因此,一旦登录,该应用程序将加载以下组件:

export class MyComponent implements OnInit {
  myService: MyService;

  constructor( private _myService: MyService ) {
    this.myService = _myService;
  }

  ngOnInit() {
   this._myService.loadAPI();
  }

}

组件html包含以下标记

<iframe id="player" type="text/html" width="640" height="360"
      src="http://www.youtube.com/embed/M7lc1UVf-VE?enablejsapi=1"
      frameborder="0" allowfullscreen></iframe>

最后,该服务具有以下内容

player: YT.Player;

  loadAPI(){
    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag,firstScriptTag);
    console.log('API loaded'); // this is shown on the console.
  }

  onYouTubeIframeAPIReady(){
    this.player = new YT.Player('player',{
      events: {
        'onReady': this.onPlayerReady,'onStateChange': this.onPlayerStateChange
      }
    });
    console.log('youtube iframe api ready!'); // this is never triggered.
  }

  onPlayerReady(event){
    event.target.playVideo();
  }

  onPlayerStateChange(status){
    console.log(status.data);
  }

我已经读过API自动调用函数“onYouTubeIframeAPIReady”,所以我想知道我应该做些什么来让它正常工作.

您需要在全局对象上定义您的函数onYouTubeIframeAPIReady.这与JavaScript的链接答案完全相同.
接下来是这里所有100%的JavaScript内容,通过其JavaScript性质的超集适用于TypeScript.

如果您正在使用模块(通常是Angular 2应用程序的情况),那么您的代码将被隔离,并且认情况下不会在全局范围内执行.这意味着为了定义全局,我们需要获得对全局对象的引用.在浏览器中,这非常简单,因为窗口指的是全局(除非它被遮蔽).

你需要写的东西非常简单.它本质上是

window.onYouTubeIframeAPIReady = function () { ... };

这意味着获取当前的代码,如下所示

export default class YouTubeService {
  ...
  loadAPI() {
    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag,firstScriptTag);
    console.log('API loaded'); // this is shown on the console.
  }

  onYouTubeIframeAPIReady() { }
}

并将其改为此

export default class YouTubeService {
  ...
  loadAPI() {
    window.onYouTubeIframeAPIReady = function () { };

    var tag = document.createElement('script');
    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag,firstScriptTag);
    console.log('API loaded'); // this is shown on the console.
  }
}

您将收到TypeScript错误,告诉您该窗口没有onYouTubeIframeAPIReady的定义.这很容易通过多种方式解决,但我只是说明两种可能性,要么就是完成工作,技术上也没有必要,因为尽管出现错误,TypeScript仍然会发出代码.

>在窗口上指定一个类型断言来抑制错误

(window as any).onYouTubeIframeAPIReady = function () {}

>在窗口上声明成员,以便您可以分配给它而不会出现错误.在模块内部(回想一下,我们不在全球范围内),我们可以使用以下形式

declare global {
  interface Window {
    onYouTubeIframeAPIReady?: () => void;
  }
}

请记住,所有JavaScript都是有效的TypeScript,并且TypeScript不会向JavaScript添加行为或功能.它是一种类型化的视图,如果您愿意,可以通过JavaScript进行解释,允许对其进行静态验证并具有出色的工具,捕获错误,提供高效的编辑体验,并允许在代码级别记录期望.

这只是JavaScript.它与Youtube iframe api not triggering onYouTubeIframeAPIReady中使用的解决方案完全相同,我只发布它,因为似乎有断开连接.

附录:值得注意的是,如果使用SystemJS或RequireJS等模块加载程序,则可以通过加载程序配置抽象手动脚本标记注入过程.这样做的好处是更清晰,更具说明性的代码以及更高的可测试性,因为您可以存储YouTube依赖关系,将测试与网络隔离开来.

对于SystemJS,您将使用以下配置

SystemJS.config({
  map: {
    "youtube": "https://www.youtube.com/iframe_api"
  },Meta: {
    "https://www.youtube.com/iframe_api": {
      "format": "global","scriptLoad": true,"build": false
    }
  }
});

你可以写

export default class YouTubeService {
  async loadAPI() {
    window.onYouTubeIframeAPIReady = function () {
      console.log('API loaded'); // this is shown on the console.
    };
    try {
      await import('youtube'); // automatically injects a script tag
    }
    catch (e) {
      console.error('The YouTube API Failed to load');
    }
  }
}

declare global {
  interface Window {
    onYouTubeIframeAPIReady?: () => void;
  }
}

现在,如果您想测试此代码,模拟YouTube API,您可以写

测试/检验存根/存根的YouTube-api.ts

(function () {
  window.onYouTubeIframeAPIReady();
}());

测试/服务/ YouTube的-service.spec.ts

import test from 'blue-tape';

import YouTubeService from 'src/services/youtube.service'

SystemJS.config({
  map: {
    "youtube": "test/test-stubs/stub-youtube-api.ts"
  }
});

if(typeof window === 'undefined') {
  global.window = {};
}


test('Service must define a callback for onYouTubeIframeAPIReady',async ({isNot}) => {
  const service = new YouTubeService();
  await service.loadAPI();
  t.isNot(undefined,window.onYouTubeIframeAPIReady);
});

原文地址:https://www.jb51.cc/angularjs/142521.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐