0

プロパティの値を非同期的にロードするモジュール (module1) を定義しました。このプロパティを定義したらすぐに、定義後にのみアプリで使用するにはどうすればよいですか?

私のセットアップ(簡略化)

v1

app.js

require(['module1'], function(mod) {
    document.getElementById("greeting").value = mod.getPersonName();
});

module1.js

define(['jquery'], function($) {
    _person;

    $.get('values/person.json')
        .done(function(data) {
            _person = data
        });

    return {
        getPersonName: function() { return _person.name; }
    }

値/person.json

{ name: 'John Doe', age: 34 }    

これは、GET がほぼ瞬時に行われる場合にのみ機能します。それ以外の場合は、getPersonName が呼び出されたときに _person が定義されていないため、失敗します。

v2

これに対抗するために、人がロードされたときにアプリに通知するコールバックを登録することにしました。

app.js

require(['module1'], function(mod) {
    mod.onPersonLoaded(function() {
        document.getElementById("greeting").value = mod.getPersonName();
    });
});

module1.js

define(['jquery'], function($) {
    _person;
    _onLoaded;

    $.get('values/person.json')
        .done(function(data) {
            _person = data;
            _onLoaded();
        });

    return {
        getPersonName: function() { return _person.name; },
        onPersonLoaded: function(cb) { _onLoaded = cb; }
    }
}

これは、GET が遅い場合は機能しますが、速い場合は _onLoaded が.done()呼び出されたときに未定義です。

app.js で _person 値が定義されるとすぐに、定義されたときにのみ使用する良い方法はありますか?

私は RequireJS を使用していますが、私の質問は一般的に AMD に当てはまります。

編集

例を単純化するために、重要なレイヤーを削除しました。UI には RactiveJS を使用しています。

セットアップ (やや簡素化)

app.js

require(['Ractive', 'module1'], function(Ractive, mod) {

    var ractive = new Ractive({
        ...
        data : {
            name: mod.getPersonName()
        }
    });

    ractive.observe(...);
    ractive.on(...);

});

編集 2

私の現在の解決策は、変更される可能性があります。person がロードされたときに app.js に通知するコールバックを登録します。コールバックが登録されているときに person がすでにロードされている場合、コールバックはすぐに呼び出されます。

app.js

require(['Ractive', 'module1'], function(Ractive, mod) {

    var ractive = new Ractive({
        ...
        data : {}
    });

    mod.watchPerson(function() {
        ractive.set('person.name', mod.getPersonName());
    });

    ractive.observe(...);
    ractive.on(...);

});

module1.js

define(['jquery'], function($) {
    _person;
    _onLoaded;

    $.get('values/person.json')
        .done(function(data) {
            _person = data;
            try {
                _onLoaded();
            } catch (e) {
                // that was fast!
                // callback will be called when it is registered
        });

    return {
        getPersonName: function() { return _person.name; },
        watchPerson: function(cb) { 
            _onLoaded = cb;
            if(_person != null) {
                _onLoaded();
            }
        }
    }
}
4

2 に答える 2

2

コールバックは常に_onLoaded()非同期で呼び出されるため、ここでは Promise を選択することをお勧めします。設計される前に呼び出されるという紛らわしい状況に遭遇することはありません。

残念ながら、jQuery の promise 実装はPromises/A+ 仕様に準拠していないため、その保証は得られません。可能であれば、 Reqwestなどの代替 AJAX ライブラリを使用して、次のようなことを行うことができます

app.js

define(['module1'], function (mod) {
  mod.then(function(person) {
    // do something with person.name
  }
});

module1.js

define(['reqwest'], function (reqwest) {
  return reqwest('values/person.json');
});

テキストローダープラグインの使用

すでに AMD を使用しているため、もう 1 つのオプションは、 textなどのローダー プラグインを使用することです。

app.js

define(['module1'], function (person) {
  // do something with person.name
});

module1.js

define(['text!values/person.json'], function (personJSON) {
  return JSON.parse(personJSON);
});

テキストローダープラグインの使用

実際にはJSON pluginさえあるので、この例の状況では module1 を完全になくすことができます:

app.js

define(['json!values/person'], function (person) {
  // do something with person.name
});
于 2014-01-28T01:25:49.437 に答える