我确信“内在要求”不是正确的术语,但很快就会有意义。我正在从工具包的网站上学习Dijit教程,我遇到了一个问题,我认为这个问题比Dojo更容易理解Javascript。
我的页面初始化脚本:
require(['player', 'dojo/dom', 'ready'], function(Player, dom){
var p = new Player({
type : 'video',
dimensions : [720, 480]
});
p.setSource('videos/myvideo.webm')
p.placeAt(dom.byId('stage') )
})
我的dijit“player.js”的构造函数
constructor : function(opts){
(function($){
require(['sg/player/component/Video', 'sg/player/component/Audio'], function(Video, Audio){
$._setMedia( (opts.type == 'video') ? new Video() : new Audio());
console.log($._media) // outputs an object "a"
})
})(this);
console.log(this._media) // also outputs the correct object, "a"
}
// the internal setter function used above
_setMedia : function(m){
this._media = m;
},
(我有一个匿名函数的原因是我不喜欢在var self = this
块中分配require
,this
不是包含对象。)
当我在init脚本中创建new Player()
对象时,我可以看到正确分配了Audio
或Video
的新实例。但是,当我在init脚本中调用p.setSource()
时,出现_media
为空的错误!
步骤
_media
对象包含Video
或Audio
Player
来源之外访问setter方法!错误!! 所以我的问题,希望我提供了足够的背景,但为什么_media
变量会失去它的价值?要从Dijit源外部访问的Player
实例中的任何方法都不应该对内部变量的范围产生任何影响,但这似乎正在发生。构造函数返回后,应设置_media
!但是使用
setSource : function(s){
console.log('Setting source: ', s, this._media)
// outputs ("Setting source: path/to/video.webm', null)
},
...抛出一个错误,因为它在_media
内引用的setSource
变量被认为是空的。
希望很清楚:)
希望我能给你们两个勾选标记!感谢您抽出宝贵时间提供帮助。
@Frode:肯定有一些异步问题迫使我学习并尝试更多结构,所有这些都失败了,导致了这次更新。我认为在某些时候文件被缓存,导致变量内容不一致。
@phusick:我将您的建议与下面发布的内容混合在一起。
我考虑重做玩家将如何实例化的结构,对象arg等,但决定做以下事情,万一有人遇到这个问题......
我将Audio
和Video
类合并到_Media
文件中,使用此结构(为简洁起见,删除了代码)
define(['dojo/_base/declare'], function(declare){
var _base = declare("_Media", null, {
constructor : function(type){
this._type = type;
},
// etc
})
return {
Video : function(){
return declare("Video", _base, {
constructor : function(){
this.inherited(arguments, ['video'])
}
// etc
})()
},
Audio : function(){
return declare("Audio", _base, {
constructor : function(){
this.inherited(arguments, ['audio'])
}
// etc
})()
},
}
})
...这样一来,最初只加载了一个文件,它包含两个子类。当不使用一个文件时,比装载2个单独的文件更好,IMO。
对于玩家类型实例,它变为:
this._media = opts.type && opts.type == 'video' ? new Media.Video() : new Media.Audio();
到目前为止一切顺利!再次感谢。
答案 0 :(得分:1)
构造函数返回后,应设置_media!
我认为这是你采取错误措施的地方。请记住,require是一个异步函数!
但是,我对你的构造函数中的这一行(特别是注释)感到有点困惑:
console.log(this._media) // also outputs the correct object, "a"
你是100%确定这输出“a”而不是null吗?如果你是,请忽略我的其余答案,因为那时我误解了一些事情:)
好的,如果您还在阅读,我会尝试解释异步需求。当你打电话:
require([".../Video",".../Audio"], function(Video, Audio) {
// do something and set _media
});
你基本上是在说:“浏览器,你在后台为我提取视频和音频模块,而我继续我的下一行代码。当你提取它们时,运行我给你的功能集_media“。
换句话说,在require()完成并设置_media
之前可能需要很长时间,但您的代码会立即继续。所以当你调用setSource时,require()可能还没有完成(事实上,它甚至可能没有开始下载任何东西)。
希望有所帮助!
答案 1 :(得分:1)
@Frode是对的。实际上,即使异步操作足够快也无法工作,因为JavaScript是单线程的,异步回调进入事件队列并通过Event Loop一个接一个地执行。
请参阅我对Dojo 1.7 how to use dojo components outside of require()的回答。
你的 player.js 是否有任何理由不这样:
define([
"sg/player/component/Video",
"sg/player/component/Audio"
], function(
Video,
Audio
) {
return declare([SomeSuperClass], {
constructor: function(opts) {
var media = opts.type && opts.type == "video" ? new Video() : new Audio();
this._setMedia(media);
}
});
});