8

我正在尝试在 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 文件的头标记中,有时会加载 API。这一切都是意料之中的,但我不明白,因为异步插件失败了。

感谢您的关注和帮助:)

4

5 回答 5

14

我不熟悉asyncrequireJS 插件,但这里有一些示例代码(取自YouTube Direct Lite),它从名为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;
});
于 2012-10-13T03:32:21.070 回答
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({ ... });

    }
);

也适用于内联 require 调用:

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 作为第一个插件参数。任何如何使它更美丽和简单的想法都非常受欢迎。

于 2013-10-29T20:32:41.340 回答
6

第 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功能并且您正在开展业务

于 2015-07-08T21:34:15.833 回答
3

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

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
          }
        });
};
于 2013-07-15T16:09:56.917 回答
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({...});
});
于 2013-10-14T08:21:25.133 回答