プロパティの値を非同期的にロードするモジュール (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();
}
}
}
}