使用RequireJS加载Youtube iframe API

时间:2012-10-11 15:59:22

标签: javascript youtube-api requirejs

我正在尝试在使用Require JS定义的模块中使用Youtube Iframe API。由于这个API加载了异步并且在加载后调用了一个函数,我使用了一个名为“async”的requireJS插件,之前使用google maps api。

然而,这次有些事情没有用。我的模块以这种方式启动: define(['text!fmwk/widgets/video/video.html','fmwk/utils/browser','async!http://www.youtube.com/iframe_api'], function (videoTpl,root) { ... });

和chrome控制台触发此错误: Uncaught Error: Load timeout for modules: async!http://www.youtube.com/iframe_api_unnormalized3,async!http://www.youtube.com/iframe_api http://requirejs.org/docs/errors.html#timeout

如果我不使用异步插件,则对象YT或其功能未定,如果我下载API代码也会发生同样的情况。如果我将脚本标记放在html文件的head标记中,有时会加载API。所有这些都是预期的,但我不明白,因为异步插件失败了。

感谢您的关注和帮助:)。

5 个答案:

答案 0 :(得分:14)

我不熟悉async requireJS插件,但是这里有一些示例代码(取自YouTube Direct Lite),它从名为的requireJS模块中异步加载iframe API player。不过,它使用jQuery来进行实际的库加载。

define(['jquery'], function($) {
  var player = {
    playVideo: function(container, videoId) {
      if (typeof(YT) == 'undefined' || typeof(YT.Player) == 'undefined') {
        window.onYouTubeIframeAPIReady = function() {
          player.loadPlayer(container, videoId);
        };

        $.getScript('//www.youtube.com/iframe_api');
      } else {
        player.loadPlayer(container, videoId);
      }
    },

    loadPlayer: function(container, videoId) {
      new YT.Player(container, {
        videoId: videoId,
        width: 356,
        height: 200,
        // For a list of all parameters, see:
        // https://developers.google.com/youtube/player_parameters
        playerVars: {
          autoplay: 1,
          controls: 0,
          modestbranding: 1,
          rel: 0,
          showinfo: 0
        }
      });
    }
  };

  return player;
});

答案 1 :(得分:6)

经过一些研究并对其他答案不满意后,我已经通过扩展require async解决了这个问题以及其他可能没有额外漏洞的情况!插件支持命名回调,然后确保模块代码仅在API完全加载后执行。

核心问题似乎是,YouTube Iframe API不允许您配置回调的名称,但要求它为“onYouTubeIframeAPIReady”,我们对异步插件的小升级解决了这个问题。这个解决方案仍然使用全局window.YT,但不使用jQuery。

require(
    ['async!//www.youtube.com/iframe_api!undefined:onYouTubeIframeAPIReady'],
    function() { 

        // this codes executes your code once YouTube Iframe API is loaded and ready
        player = new YT.Player({ ... });

    }
);

也适用于内联需求调用:

define([], function () {
    // .. some of your other code here

    require(['async!//www.youtube.com/iframe_api!undefined:onYouTubeIframeAPIReady'],      function () {

        // this codes executes your code once YouTube Iframe API is loaded and ready
        player = new YT.Player({ ... });

    });
});

在我看来,代码比以前更清晰。此外,通过在最后一刻加载API的性能提升是巨大的,特别是当与数十个玩家一起使用时。 API当然只会加载一次并像往常一样缓存。

升级!async插件: https://github.com/mhrisse/requirejs-plugins/blob/master/src/async.js

拉升级!async插件的请求: https://github.com/millermedeiros/requirejs-plugins/pull/39

升级应完全向后兼容,即 为什么有这个相当丑陋的undefined作为第一个插件参数。任何想法如何使这更美丽和简单是非常受欢迎的。

答案 2 :(得分:5)

第1步:要求没有广告的YouTube



require.config({
  ...
  youtube: '//www.youtube.com/iframe_api?noext',
  ...
})




第2步:将onYouTubeIframeAPIReady函数附加到窗口对象



var player;
window.onYouTubeIframeAPIReady = function(){
  player = new YT.Player('player', {
    height: '390',
    width: '640',
    videoId: 'M7lc1UVf-VE',
  });
};




第3步:异步加载脚本



require(['youtube']);




这将触发您的onYouTubeIframeAPIReady功能并且您正在开展业务

答案 3 :(得分:3)

使用require的另一个选项是加载外部javascript并在加载javascript时发出带有上下文的jQuery promise回调。

this.initVideo = function emebdvideo(){
        //Have we already loaded the youtube iframe API?
        if(typeof YT === 'undefined' || typeof YT.Player == 'undefined'){
            var loaded = this.loadYTapi();
            loaded.done(this.embedVideo);
        }else{
            this.embedVideo();
        }

};

this.loadYTapi = function loadYTapi(){

        var dfd = $.Deferred(),
        context = this;

        //Load youtube js with require
        require(['https://www.youtube.com/iframe_api'], function(){
            window.onYouTubeIframeAPIReady = function() {

                //Resolve with context
                dfd.resolveWith(context);
            };
        });

        return dfd;
};

this.embedVideo = function embedVideo(){

        var youtubeId = 'youtube-id';
        var player = new YT.Player('player', {
          height: '390',
          width: '640',
          videoId: youtubeId,
          events: {
            'onReady': this.onPlayerReady,
            'onStateChange': this.onPlayerStateChange
          }
        });
};

答案 4 :(得分:3)

配置requirejs

require.config({
    paths: {
        // Notice the ?noext query parameter. It is added to prevent from requirejs to add .js extension
        youTubeIFrame: 'https://www.youtube.com/iframe_api?noext'
    },
    shim: {
        youTubeIFrame: {
            // Now requirejs expects a YT global variable to be initialized
            // http://requirejs.org/docs/api.html#config-shim
            exports: 'YT'
        }
    }
 });

用法

require(['youTubeIFrame'], function(YT) {
    // Here YT will be already available because requirejs waited for this global variable to be initialized.
    // No need to define a global function onYouTubeIframeAPIReady
    new YT.Player({...});
});