Javascript Dojo范围问题,带有;“内部”;要求

Javascript Dojo范围问题,带有;“内部”;要求,javascript,dojo,Javascript,Dojo,我确信“内在需求”不是正确的术语,但它很快就会有意义。我正在工具包的网站上编写Dijit教程,我遇到了一个问题,我认为这更像是一个Javascript理解问题,而不是Dojo理解问题 我的页面初始化脚本: require(['player', 'dojo/dom', 'ready'], function(Player, dom){ var p = new Player({ type : 'video', dimensions : [720, 480]

我确信“内在需求”不是正确的术语,但它很快就会有意义。我正在工具包的网站上编写Dijit教程,我遇到了一个问题,我认为这更像是一个Javascript理解问题,而不是Dojo理解问题

我的页面初始化脚本:

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”构造函数

(我在那里使用匿名函数的原因是我不喜欢将
var self=this
赋值为
require
块中的
this
不是包含的对象。)

当我在init脚本中创建
new Player()
对象时,我可以看到
Audio
Video
的新实例被正确分配。但是,当我在init脚本中调用
p.setSource()
时,我得到一个错误,即
\u media
为空

步骤

  • 创建玩家
    • 解析配置选项(类型、维度等)。内部
      \u media
      对象保存
      视频
      音频
  • 允许setter方法在
    播放器之外访问
    !!错误
所以我的问题,希望我给出了足够的上下文,但是为什么
\u media
变量失去了它的值呢?从Dijit源代码之外访问
Player
实例中的任何方法都不应该对内部变量的范围产生任何影响,但这似乎是正在发生的事情。构造函数返回后,应设置
\u media
!但是使用

setSource : function(s){
    console.log('Setting source: ', s, this._media)
    // outputs ("Setting source: path/to/video.webm', null)
},
…引发错误,因为它在
setSource
中引用的
\u媒体
变量假定为空

希望这是清楚的:)

更新

但愿我能给你们两个打勾!谢谢你抽出时间帮忙

@弗罗德:肯定有一些异步问题迫使我学习和尝试更多的结构,所有这些都失败了,导致这次更新。我认为在某些情况下,文件被缓存,导致变量内容不一致

@普西克:我混合了你的建议,贴在下面

我曾考虑过重做播放器的实例化结构、对象arg等,但决定做以下操作,以防有人碰到这个问题

我使用此结构将
音频
视频
类合并到
\u媒体
文件中(为简洁起见删除了代码)

…这样一来,最初只加载一个文件,并且它包含两个子类。IMO说,这比在一个文件不使用时加载两个单独的文件要好

对于玩家类型实例,它变成:

this._media = opts.type && opts.type == 'video' ? new Media.Video() : new Media.Audio();
到目前为止还不错!再次感谢

构造函数返回后,应设置\u介质

我认为这是你迈出错误的一步。请记住,require是一个异步函数

但是,我对构造函数中的这一行(特别是注释)有点困惑:

您是否100%确定输出“a”而不是空值?如果你是,请忽略我其余的回答,因为这样我就误解了:)

好的,如果你还在读,我会试着解释一下。当你打电话时:

require([".../Video",".../Audio"], function(Video, Audio) {
    // do something and set _media
});
你基本上是说:“浏览器,你去后台为我取视频和音频模块,我继续我的下一行代码。当你取完它们后,运行我给你的功能,设置媒体。”

换句话说,require()完成并设置
\u media
可能需要很长时间,但您的代码会立即继续。因此,当您调用setSource时,require()可能还没有完成(实际上,它甚至可能还没有开始下载任何东西)


希望有帮助

@Frode是对的。事实上,即使异步操作足够快,它也不会工作,因为JavaScript是单线程的,异步回调进入事件队列并通过一个接一个地执行

请参阅我对这一问题的答复

你的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);
        }
    });

});

我明白了。。。感谢您提醒我们
require
的异步性质。我看了更多的文档,根据你的回答,我学到了一两件事。稍后我会继续研究,并提供更新。有趣的是,在你回应之前不久,你在屋外研究时提到了我看到的链接。我不立即加载视频和音频的原因是它们可能不需要。我需要一个同步的条件require块,我会看看延迟,但我可能只是将音频和视频合并到一个媒体类/文件中。谢谢
console.log(this._media) // also outputs the correct object, "a"
require([".../Video",".../Audio"], function(Video, Audio) {
    // do something and set _media
});
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);
        }
    });

});