未捕获的类型错误:YT.Player 不是构造函数

Bob*_*ona 8 javascript youtube-api

我希望有人可以帮助解决这个问题。当我在我的页面上大约 5 个选项卡上时,我收到以下错误 Uncaught TypeError: YT.Player is not a constructor。我点击页面上的一个按钮,它会弹出一个模态窗口,我从中进行选择,并在控制台中的模态窗口关闭时显示错误。

令人沮丧的是,使用与生产相同的数据和相同的编译参数,我无法在我们的开发或暂存环境中复制自己的错误。一个区别是我们的生产服务器位于 NetScaler 后面。NetScaler 可能是问题所在吗?

下面是我的视频代码。

<div class="videocontainer">
        @if (!string.IsNullOrEmpty(video.VideoURL))
        {

            <script type="text/javascript">
                var _gVideoTracked = false;
                var player;
                function onYouTubeIframeAPIReady() {
                    player = new YT.Player('player', {
                        events: { 'onStateChange': onPlayerStateChange }
                    });
                }
                function onPlayerStateChange(event) {
                    switch (event.data) {
                        case 0:
                            break;
                        case 1:
                            if (!_gVideoTracked) {
                                BaGaTrack('Video Played', 'Played')
                            }
                            _gVideoTracked = true;
                            break;
                        case 2:

                    }
                }
                $(document).ready(function () {
                    $.getScript("https://www.youtube.com/iframe_api", function () {
                        player = new YT.Player('player', {
                            events: { 'onStateChange': onPlayerStateChange }
                        });
                    });
                });
            </script>
            <iframe id="player" src="@video.VideoURL/?enablejsapi=1" allowfullscreen class="video"></iframe>
        }

    </div>
Run Code Online (Sandbox Code Playgroud)

dan*_*die 8

好像有一个未公开的API, YT.ready。
在他们的文档中找不到:https : //developers.google.com/youtube/iframe_api_reference

就我而言,我不得不包new YT.Player内YT.read(),如下图所示。

 function setupPlayer() {
    /**
     * THIS FAILS!!!!!
     */
    // player = new YT.Player("player", {
    //   height: "390",
    //   width: "640",
    //   videoId: "M7lc1UVf-VE",
    //   events: {
    //     onReady: onPlayerReady,
    //     onStateChange: onPlayerStateChange
    //   }
    // });

    /**
     * Need to wait until Youtube Player is ready!
     */
    window.YT.ready(function() {
      player = new window.YT.Player("video", {
        height: "390",
        width: "640",
        videoId: "M7lc1UVf-VE",
        events: {
          onReady: onPlayerReady,
          onStateChange: onPlayerStateChange
        }
      });
    });
  }
Run Code Online (Sandbox Code Playgroud)

我是通过这个 CodeSanbox 示例找到的,https: //codesandbox.io/s/youtube-iframe-api-tpjwj

它使用 jQuery,我使用下面的 Vanilla JS 重新实现了它。
https://codesandbox.io/s/soanswer52062169-mem83

为了完整起见,这里是 JavaScript 代码。

function loadVideo() {
  console.info(`loadVideo called`);

  (function loadYoutubeIFrameApiScript() {
    const tag = document.createElement("script");
    tag.src = "https://www.youtube.com/iframe_api";

    const firstScriptTag = document.getElementsByTagName("script")[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    tag.onload = setupPlayer;
  })();

  let player = null;

  function setupPlayer() {
    /**
     * THIS FAILS!!!!!
     */
    // player = new YT.Player("player", {
    //   height: "390",
    //   width: "640",
    //   videoId: "M7lc1UVf-VE",
    //   events: {
    //     onReady: onPlayerReady,
    //     onStateChange: onPlayerStateChange
    //   }
    // });

    /**
     * Need to wait until Youtube Player is ready!
     *
     * YT.ready is not documented in https://developers.google.com/youtube/iframe_api_reference
     * but found from https://codesandbox.io/s/youtube-iframe-api-tpjwj
     */
    window.YT.ready(function() {
      player = new window.YT.Player("video", {
        height: "390",
        width: "640",
        videoId: "M7lc1UVf-VE",
        events: {
          onReady: onPlayerReady,
          onStateChange: onPlayerStateChange
        }
      });
    });
  }

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

  function onPlayerStateChange(event) {
    var videoStatuses = Object.entries(window.YT.PlayerState);
    console.log(videoStatuses.find(status => status[1] === event.data)[0]);
  }
}

if (document.readyState !== "loading") {
  console.info(`document.readyState ==>`, document.readyState);
  loadVideo();
} else {
  document.addEventListener("DOMContentLoaded", function() {
    console.info(`DOMContentLoaded ==>`, document.readyState);
    loadVideo();
  });
}

Run Code Online (Sandbox Code Playgroud)


Jam*_*ins 7

事实证明,同步包含 API 并不重要(使用 URL https://www.youtube.com/iframe_api),因为返回的代码无论如何都会异步加载 API。这些说明具有误导性(数字),给人的印象是使用直接脚本链接加载将是同步的,但事实并非如此。因此new YT.Player失败只是因为玩家“类型”是undefined.

这是您需要等待的事件:

任何使用 IFrame API 的网页还必须实现以下 JavaScript 函数:

onYouTubeIframeAPIReady – 当页面完成下载播放器 API 的 JavaScript 后,API 将调用此函数,这样您就可以在页面上使用 API。因此,此函数可能会创建您希望在页面加载时显示的播放器对象。

警告:在播放器本身完成加载(触发“就绪”事件)之前,某些特定于播放器的功能也会丢失。