我正在尝试在使用Require JS定义的模块中使用Youtube Iframe API。由于这个API加载了异步并且在加载后调用了一个函数,我使用了一个名为“async”的requireJS插件,之前使用google maps api。
然而,这次有些事情没有用。我的模块以这种方式启动:
define(['text!fmwk/widgets/video/video.html','fmwk/utils/browser','async!http://www.youtube.com/iframe_api'], function (videoTpl,root) { ... });
和chrome控制台触发此错误:
Uncaught Error: Load timeout for modules: async!http://www.youtube.com/iframe_api_unnormalized3,async!http://www.youtube.com/iframe_api
http://requirejs.org/docs/errors.html#timeout
如果我不使用异步插件,则对象YT或其功能未定,如果我下载API代码也会发生同样的情况。如果我将脚本标记放在html文件的head标记中,有时会加载API。所有这些都是预期的,但我不明白,因为异步插件失败了。
感谢您的关注和帮助:)。
答案 0 :(得分:14)
我不熟悉async
requireJS插件,但是这里有一些示例代码(取自YouTube Direct Lite),它从名为的requireJS模块中异步加载iframe API player
。不过,它使用jQuery来进行实际的库加载。
define(['jquery'], function($) {
var player = {
playVideo: function(container, videoId) {
if (typeof(YT) == 'undefined' || typeof(YT.Player) == 'undefined') {
window.onYouTubeIframeAPIReady = function() {
player.loadPlayer(container, videoId);
};
$.getScript('//www.youtube.com/iframe_api');
} else {
player.loadPlayer(container, videoId);
}
},
loadPlayer: function(container, videoId) {
new YT.Player(container, {
videoId: videoId,
width: 356,
height: 200,
// For a list of all parameters, see:
// https://developers.google.com/youtube/player_parameters
playerVars: {
autoplay: 1,
controls: 0,
modestbranding: 1,
rel: 0,
showinfo: 0
}
});
}
};
return player;
});
答案 1 :(得分:6)
经过一些研究并对其他答案不满意后,我已经通过扩展require async解决了这个问题以及其他可能没有额外漏洞的情况!插件支持命名回调,然后确保模块代码仅在API完全加载后执行。
核心问题似乎是,YouTube Iframe API不允许您配置回调的名称,但要求它为“onYouTubeIframeAPIReady”,我们对异步插件的小升级解决了这个问题。这个解决方案仍然使用全局window.YT,但不使用jQuery。
require(
['async!//www.youtube.com/iframe_api!undefined:onYouTubeIframeAPIReady'],
function() {
// this codes executes your code once YouTube Iframe API is loaded and ready
player = new YT.Player({ ... });
}
);
也适用于内联需求调用:
define([], function () {
// .. some of your other code here
require(['async!//www.youtube.com/iframe_api!undefined:onYouTubeIframeAPIReady'], function () {
// this codes executes your code once YouTube Iframe API is loaded and ready
player = new YT.Player({ ... });
});
});
在我看来,代码比以前更清晰。此外,通过在最后一刻加载API的性能提升是巨大的,特别是当与数十个玩家一起使用时。 API当然只会加载一次并像往常一样缓存。
升级!async插件: https://github.com/mhrisse/requirejs-plugins/blob/master/src/async.js
拉升级!async插件的请求: https://github.com/millermedeiros/requirejs-plugins/pull/39
升级应完全向后兼容,即 为什么有这个相当丑陋的undefined作为第一个插件参数。任何想法如何使这更美丽和简单是非常受欢迎的。
答案 2 :(得分:5)
第1步:要求没有广告的YouTube
require.config({
...
youtube: '//www.youtube.com/iframe_api?noext',
...
})

第2步:将onYouTubeIframeAPIReady函数附加到窗口对象
var player;
window.onYouTubeIframeAPIReady = function(){
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
});
};

第3步:异步加载脚本
require(['youtube']);

这将触发您的onYouTubeIframeAPIReady
功能并且您正在开展业务
答案 3 :(得分:3)
使用require的另一个选项是加载外部javascript并在加载javascript时发出带有上下文的jQuery promise回调。
this.initVideo = function emebdvideo(){
//Have we already loaded the youtube iframe API?
if(typeof YT === 'undefined' || typeof YT.Player == 'undefined'){
var loaded = this.loadYTapi();
loaded.done(this.embedVideo);
}else{
this.embedVideo();
}
};
this.loadYTapi = function loadYTapi(){
var dfd = $.Deferred(),
context = this;
//Load youtube js with require
require(['https://www.youtube.com/iframe_api'], function(){
window.onYouTubeIframeAPIReady = function() {
//Resolve with context
dfd.resolveWith(context);
};
});
return dfd;
};
this.embedVideo = function embedVideo(){
var youtubeId = 'youtube-id';
var player = new YT.Player('player', {
height: '390',
width: '640',
videoId: youtubeId,
events: {
'onReady': this.onPlayerReady,
'onStateChange': this.onPlayerStateChange
}
});
};
答案 4 :(得分:3)
require.config({
paths: {
// Notice the ?noext query parameter. It is added to prevent from requirejs to add .js extension
youTubeIFrame: 'https://www.youtube.com/iframe_api?noext'
},
shim: {
youTubeIFrame: {
// Now requirejs expects a YT global variable to be initialized
// http://requirejs.org/docs/api.html#config-shim
exports: 'YT'
}
}
});
require(['youTubeIFrame'], function(YT) {
// Here YT will be already available because requirejs waited for this global variable to be initialized.
// No need to define a global function onYouTubeIframeAPIReady
new YT.Player({...});
});