8

Require JS で定義されたモジュール内で Youtube Iframe API を使用しようとしています。この API は非同期で読み込まれ、読み込まれると関数が呼び出されるため、以前は Google マップ API で機能していた「async」という requireJS プラグインを使用しました。

ただし、今回は何かが機能していません。私のモジュールは次のように始まります: define(['text!fmwk/widgets/video/video.html','fmwk/utils/browser','async!http://www.youtube.com/iframe_api'], function (videoTpl,root) { ... });

そしてクロムコンソールはこのエラーを発生させます: 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タグにscriptタグを入れるとAPIが読み込まれることがあります。これはすべて想定どおりですが、非同期プラグインが失敗するためわかりません。

ご清聴ありがとうございました:)

4

5 に答える 5

14

私は requireJS プラグインに詳しくありませんが、requireJS という名前のモジュール内から iframe API を非同期的にロードするasyncサンプル コード ( YouTube Direct Liteplayerから取得) を次に示します。ただし、実際のライブラリのロードには 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 に答える
3

外部 JavaScript をロードするために require を使用し、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
          }
        });
};
于 2013-07-15T16:09:56.917 に答える