我定义了一个模块(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; }
}
values/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 速度较慢,则此方法有效,但如果速度较快,则在调用 .done()
时 _onLoaded 未定义。
有没有一种好方法可以在 app.js 中一旦定义并仅在定义后使用 _person 值?
我正在使用 RequireJS,但我的问题通常适用于 AMD。
编辑
在简化我的示例时,我删除了一个可能很重要的层。我使用 RactiveJS 作为 UI。
设置(稍微简化)
app.js
require(['Ractive', 'module1'], function(Ractive, mod) {
var ractive = new Ractive({
...
data : {
name: mod.getPersonName()
}
});
ractive.observe(...);
ractive.on(...);
});
编辑2
我当前的解决方案,可能会发生变化。注册一个回调,在加载 person 时通知 app.js。注册回调时,如果人员已经加载,则立即调用回调。
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();
}
}
}
}
最佳答案
Promise 在这里是一个不错的选择,因为回调总是异步调用 - 您永远不会遇到 _onLoaded()
在设计之前就被调用的困惑情况。
不幸的是,jQuery 的 Promise 实现并不遵守 Promises/A+ specification ,所以你得不到这个保证。如果可能,您可以使用替代 AJAX 库,例如 Reqwest ,然后做类似的事情
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,另一个选择是使用加载器插件,例如 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
});
关于javascript - 异步加载模块属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21390684/