【问题标题】:Uncaught TypeError: YT.Player is not a constructor未捕获的 TypeError:YT.Player 不是构造函数
【发布时间】:2019-02-03 08:11:10
【问题描述】:

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

令人沮丧的是,使用与生产环境相同的数据和相同的编译参数,我无法在我们的 Dev 或 Staging 环境中复制自己的错误。一个区别是我们的生产服务器位于 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>

【问题讨论】:

    标签: javascript youtube-api


    【解决方案1】:

    似乎有一个未记录的 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
            }
          });
        });
      }
    

    我通过这个 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();
      });
    }
    
    

    【讨论】:

      【解决方案2】:

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

      这是你需要等待的事件:

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

      onYouTubeIframeAPIReady – API 将在 页面已完成下载播放器 API 的 JavaScript,它 使您能够在您的页面上使用 API。因此,这个函数 可能会创建您想要在页面显示时显示的播放器对象 加载。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-17
        • 2019-02-13
        • 2018-04-09
        • 2020-07-18
        • 2019-03-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多