Ответ 1
Это не проблема с таймаутом, и вам не нужно запускать эту функцию вручную.
Убедитесь, что ваша функция onYouTubeIframeAPIReady
доступна на глобальном уровне, а не вложен (скрыта) в другой функции.
Я уже много лет сражаюсь с youtube iframe api. Почему-то метод onYouTubeIframeAPIReady
не всегда срабатывает.
От симптомов кажется проблемой загрузки. В инспекторе не отображаются ошибки.
Вот мой код:
<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>
(вызывается в конце страницы. Я попытался поместить код сразу после выше script, и результат был тем же.)
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
, и ничего не происходит.
На мобильных телефонах это происходит постоянно. Любые идеи?
Это не проблема с таймаутом, и вам не нужно запускать эту функцию вручную.
Убедитесь, что ваша функция onYouTubeIframeAPIReady
доступна на глобальном уровне, а не вложен (скрыта) в другой функции.
Вы всегда можете присоединить его к объекту окна, чтобы убедиться, что он вызван глобально. Это полезно, если ваш код использует amd.
window.onYouTubeIframeAPIReady = function() {}
Если вам нужно внести внутрь функцию, одно из возможных решений вместо:
function onYouTubeIframeAPIReady() {
// func body...
}
вы можете объявить его следующим образом:
window.onYouTubeIframeAPIReady = function() {
// func body...
}
В этом случае убедитесь, что вы вставляете определенный script в dom после объявления (вызов insertBefore()
, который находится в глобальной области теперь в вашем случае):
Если вы загрузите код API IFrame Player асинхронно следующим образом:
<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 следующим образом:
<script src="http://www.youtube.com/player_api"></script>
то функция onYouTubeIframeAPIReady
не будет вызываться из-за того, что один и тот же код загружается дважды (функция вызывается только один раз, когда api полностью загружен).
Итак, используйте только один из способов в соответствии с вашими потребностями.
Убедитесь, что вы тестируете страницу, фактически загрузив ее в Интернете, а не только загрузив ее локально. поведение API iFrame YouTube является непоследовательным/недетерминированным
После пересмотра этого вопроса, я нашел для меня рабочее решение при использовании webpack (или я предполагаю любую другую систему модулей commongJS), или если вы найдете, что apt YouTube готов до вашего собственного JS файла, нужно использовать интервал - до тех пор, пока youtube обеспечивает обратную связь с обещаниями:
var checkYT = setInterval(function () {
if(YT.loaded){
//...setup video here using YT.Player()
clearInterval(checkYT);
}
}, 100);
В моем случае это было наиболее ошибочно.
У меня была аналогичная проблема. В моем случае onYouTubeIframeAPIReady вызывался так быстро, что фактическая реализация не была готова для правильного вызова. Поэтому после вызова youtube player_api я добавил простую реализацию с var для проверки onYouTubeIframeAPIReady так:
<script src="http://www.youtube.com/player_api"></script>
<script>
var playerReady = false
window.onYouTubeIframeAPIReady = function() { //simple implementation
playerReady = true;
}
</script>
</header>
.
.
.
<body>
<script>
window.onYouTubeIframeAPIReady = function() { //real and fully implemented
var player; // ... and so on ...
}
if(playerReady) { onYouTubeIframeAPIReady(); console.log("force to call again") }
</script>
Я на самом деле сделал это для ленивой загрузки проигрывателя 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);
}
Я смог выполнить эту работу практически во всех обстоятельствах с помощью простого setTimeout при загрузке страницы. Не знаю, я знаю, но это просто еще одна проверка, которая исправляет проблему большую часть времени.
setTimeout(function(){
if (typeof(player) == 'undefined'){
onYouTubeIframeAPIReady();
}
}, 3000)