Youtube iframe api没有触发YouYouTubeIframeAPIReady

时间:2012-09-04 03:21:52

标签: javascript jquery iframe youtube youtube-api

我一直在与youtube iframe api争夺很长一段时间。不知何故,方法onYouTubeIframeAPIReady并不总是被触发。

从症状看起来似乎是装载问题。检查员没有显示任何错误。

这是我的代码:

HTML

<div id="player"></div>
          <script>
            videoId = 'someVideoId';
            var tag = document.createElement('script');
            tag.src = "//www.youtube.com/iframe_api";
            var firstScriptTag = document.getElementsByTagName('script')[0];
            firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
          </script>

JS

(在页面末尾调用。我试图将代码放在上面的脚本之后,结果是相同的。)

var isReady = false
  , player
  , poster
  , video;

$(function () {
$('.js-play').click(function (e) {
    e.preventDefault();
    interval = setInterval(videoLoaded, 100);
  });
});
function onYouTubeIframeAPIReady() {
  console.log(videoId)
  player = new YT.Player('player', {
    height: '445',
    width: '810',
    videoId: videoId,
    events: {
      'onReady': onPlayerReady//,
      //'onStateChange': onPlayerStateChange
    }
  });
}

function onPlayerReady(event) {
  isReady = true;
  console.log("youtube says play")
}

function videoLoaded (){
  if (isReady) {
      console.log("ready and play")
      poster.hide();
      video.show();

      $('body').trigger('fluidvideos');

      player.playVideo();
      clearInterval(interval);
  } 
}

问题在于,有时console.log没有打印任何内容,也没有任何事情发生。

在手机上,这种情况一直都在发生。有什么想法吗?

9 个答案:

答案 0 :(得分:64)

这不是超时问题,您不需要手动触发此功能。

确保您的onYouTubeIframeAPIReady功能在全局级别可用,而不是在另一个功能中嵌套(隐藏)。

答案 1 :(得分:43)

您始终可以将其附加到窗口对象,以确保它是全局引发的。如果您的代码使用amd,这将非常有用。

window.onYouTubeIframeAPIReady = function() {}

答案 2 :(得分:10)

如果你必须将一个功能放入内部,一个可能的解决方案是 而不是:

function onYouTubeIframeAPIReady() {
  // func body...
}

你可以这样声明:

window.onYouTubeIframeAPIReady = function() {
  // func body...
}

在这种情况下,请确保在声明后将特定脚本插入dom(insertBefore()调用现在全局范围内的内容):

答案 3 :(得分:7)

如果您按如下方式异步加载IFrame Player API代码:

<script>
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
</script>

你也加载了这样的脚本代码:

<script src="http://www.youtube.com/player_api"></script>

然后函数onYouTubeIframeAPIReady将不会被调用,因为相同的代码被加载两次(该函数在api完全加载时被调用一次)。

因此,请根据您的需要使用其中一种方式。

答案 4 :(得分:3)

确保您通过在网页上实际投放网页来测试网页,而不仅仅是在本地加载。 YouTube iFrame API behavior is inconsistent/nondeterministic

答案 5 :(得分:3)

在重新审视之后,我在使用webpack(或者我假设任何其他commongJS模块系统)时找到了一个可行的解决方案,或者如果你发现youtube api在你自己的JS文件之前已经准备就绪,那就是使用间隔 - 直到youtube提供某种形式的承诺回调:

var checkYT = setInterval(function () {
    if(YT.loaded){
        //...setup video here using YT.Player()

        clearInterval(checkYT);
    }
}, 100);

在我的案例中,这似乎是最容易出错的。

答案 6 :(得分:0)

我遇到了类似的问题,在我的案例中,YouTubeIframeAPIReady的调用速度非常快,以至于实际的实现还没有为正确的调用做好准备。因此,在youtube player_api调用之后,我添加了一个带有var的简单实现,用于验证onYouTubeIframeAPIReady,就像这样:

public abstract class AbstractDao {

@Inject
private Configuration configuration;

public ForceApi getForceAPI() {
    ApiConfig config = new ApiConfig();
    config.setClientId("test");
    config.setClientSecret("test");
    config.setUsername("test");
    config.setPassword("test");
    config.setLoginEndpoint("test");
    return new ForceApi(config);
}

}

答案 7 :(得分:0)

我实际上是为了懒惰加载youtube播放器。似乎对我来说是防弹。

window.videoApiLoaded = [];
window.videoApiLoaded.youtube = false;

function loadYoutubeVideo(videoId) {

    window.onYouTubeIframeAPIReady = function() { document.dispatchEvent(new CustomEvent('onYouTubeIframeAPIReady', {})) };

    if(window.videoApiLoaded.youtube == false) {
        var tag = document.createElement('script');
        tag.src = "https://www.youtube.com/iframe_api";
        var firstScriptTag = document.getElementsByTagName('script')[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
        window.videoApiLoaded.youtube = true;
    }

    var player;

    document.addEventListener('onYouTubeIframeAPIReady', function (e) {
        player = new YT.Player('player', {
          height: '400',
          width: '600',
          videoId: videoId,
          events: {
            'onStateChange': onYtStateChange
          }
        });

    }, false);

}

答案 8 :(得分:-7)

我几乎可以在页面加载时使用简单的setTimeout在几乎所有情况下都能完成这项工作。我知道,这并不理想,但这只是另一种能在大多数时间解决问题的检查。

setTimeout(function(){
    if (typeof(player) == 'undefined'){
        onYouTubeIframeAPIReady();
    }
}, 3000)