1

「内部要件」は正しい用語ではないと確信していますが、ここではすぐに意味があります。ツールキットのサイトから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内に割り当てるのが好きではなく、含まれているオブジェクトではないからです。)requirethis

initスクリプトでオブジェクトを作成すると、またはの新しいインスタンスが正しく割り当てられているnew Player()ことがわかります。ただし、initスクリプトでinを呼び出すと、 nullのエラーが発生します。AudioVideop.setSource()_media

手順

  • プレーヤーの作成
    • 構成オプション(タイプ、寸法など)を解析します。内部オブジェクトは、または_mediaのインスタンスを保持しますVideoAudio
  • 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がおそらくnullであるため、エラーがスローされます。

それが明確であることを願っています:)

アップデート

両方のチェックマークを付けられたらいいのにと思います。お手数をおかけしますが、よろしくお願いいたします。

@Frode:確かにいくつかの非同期の問題があり、構造を学習してさらに試す必要がありましたが、すべて失敗し、この更新につながりました。ある時点でファイルがキャッシュされ、変数の内容に一貫性がなくなったと思います。

@phusick:以下に投稿されているあなたの提案をハイブリッド化しました。

Playerのインスタンス化方法やオブジェクト引数などの構造をやり直すことを考えましたが、誰かがこの問題にぶつかった場合に備えて、次のことを行うことにしました...

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
            })()
        },
    }
})

...そうすれば、最初にロードされるファイルは1つだけで、両方のサブクラスが含まれます。1つが使用されないときに2つの別々のファイルをロードするよりも優れています、IMO。

プレーヤータイプのインスタンスの場合、次のようになります。

this._media = opts.type && opts.type == 'video' ? new Media.Video() : new Media.Audio();

ここまでは順調ですね!再度、感謝します。

4

2 に答える 2

1

コンストラクターが戻ったら、_mediaを設定する必要があります。

これはあなたが間違った一歩を踏み出すところだと思います。requireは非同期関数であることに注意してください!

ただし、コンストラクターのこの行(具体的にはコメント)に少し混乱しています。

console.log(this._media) // also outputs the correct object, "a"

これがnullではなく「a」を出力することを100%確信していますか?もしそうなら、私は何かを誤解しているので、私の答えの残りを無視してください:)

まだ読んでいるのであれば、非同期のrequireについて説明しようと思います。電話をかけるとき:

require([".../Video",".../Audio"], function(Video, Audio) {
    // do something and set _media
});

基本的には、「ブラウザ、バックグラウンドでビデオモジュールとオーディオモジュールをフェッチし、次のコード行を続行します。フェッチしたら、_mediaを設定する関数を実行します。」

つまり、require()が終了して設定されるまでに長い時間がかかる場合があり_mediaますが、コードはすぐに続行されます。したがって、setSourceを呼び出すとき、require()はまだ実行されていない可能性があります(実際、何もダウンロードを開始していない可能性があります)。

お役に立てば幸いです。

于 2012-06-18T22:03:52.307 に答える
1

@Frodeは正しいです。実際、JavaScriptはシングルスレッドであり、非同期コールバックはイベントキューに入り、イベントループを介して次々に実行されるため、非同期操作が十分に高速であっても機能しません。

require()以外でdojoコンポーネントを使用する方法については、Dojo1.7に対する私の回答も参照してください。

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

});
于 2012-06-19T01:20:37.107 に答える