タイトルの通りです。
何が困るのか。
以下のような実装を行う過程で問題に遭遇しました。
- YoutubeIframeAPIを使って動画プレイヤーを埋め込む。
- 動画プレイヤーは、コンポーネント化して使い回せるようにする。
- コンポーネント初期化時に、YoutubeIFrameAPIを読み込む。
- 複数箇所にコンポーネントを使う場合、YoutubeIFrameAPIの読み込み処理を重複させないようにしたい。
- YoutubeIFrameAPIの読み込み処理をすでに実行したかどうか、
window.onYouTubeIframeAPIReady
が定義済みかどうかで判別する
YoutubeIframeAPIを読み込むとき
それと同時に以下のように、コールバック関数であるonYouTubeIframeAPIReady
をグローバルに定義すると思います。
window.onYouTubeIframeAPIReady = function () {
console.log('onYouTubeIframeAPIReady!!');
resolve();
};
var tag = document.createElement('script');
tag.src = '//www.youtube.com/iframe_api';
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
なので、window.onYouTubeIframeAPIReady
がundefined
かどうかによって、API読み込み処理を実行済みかどうかを判別できるはず。
if (typeof window.onYouTubeIframeAPIReady !== 'undefined') {
// すでに読み込み処理済み
// window.YT.Playerが定義される(=読み込み完了)されるまで待ってから初期化
} else {
// 読み込み処理してない
}
と思うじゃん?
グローバルサイトタグの罠
ところが、YoutubeIframeAPIを読み込む前から、window.onYouTubeIframeAPIReady
が定義されていることがありました。
console.log(window.onYouTubeIframeAPIReady);
// -> function (){r&&r();q()}
なんじゃこりゃ?
よくよく調べてみると、Googleのグローバルサイトタグを読み込んだ時に、勝手に定義されるようです。
(これに気がつくまでに相当時間を取られました)
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
なので、いつまで経ってもYoutubeIframeAPIの読み込みを開始しないため、動画が再生できないという現象に遭遇することになりました。
どう対処したのか
グローバルサイトタグがなぜonYouTubeIframeAPIReadyを定義しているのかはわかりません。
しかし、この問題にどう対処したのかだけ書いておきます。
コンポーネント類の初期化を始める前に、onYouTubeIframeAPIReady
をundefined
にしてしまうことにしました。
if (typeof window.onYouTubeIframeAPIReady !== 'undefined') {
window.onYouTubeIframeAPIReady = undefined;
}
あまり良い解法だとは思いませんが、すぐ対処してとりあえず動くことが優先です。
現場からは以上です。
よりよい方法
より良い方法に行き着いたので追記。
const originalCallback = window.onYouTubeIframeAPIReady;
window.onYouTubeIframeAPIReady = function() {
if (originalCallback) originalCallback();
// Youtube API読み込み後の処理を書く
}
これなら、もともと定義されているコールバック関数も実行される。