我已经定义了一个模块(module1),它应该异步加载属性的值。如何在定义定义后立即在我的应用中使用此属性?
的 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未定义。
为了解决这个问题,我想我会注册一个回调来在人员加载时通知应用程序。
的 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作为用户界面。
的 app.js 的
require(['Ractive', 'module1'], function(Ractive, mod) {
var ractive = new Ractive({
...
data : {
name: mod.getPersonName()
}
});
ractive.observe(...);
ractive.on(...);
});
我目前的解决方案,可能会有变化。注册一个在人员加载时通知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();
}
}
}
}
答案 0 :(得分:2)
Promise是一个很好的选择,因为回调是始终异步调用 - 你永远不会遇到_onLoaded()
在设计之前被调用的混乱局面。
不幸的是,jQuery的承诺实现不符合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
});
答案 1 :(得分:0)
我就是这样做的。基本上,它与你的V2没什么不同,但它增加了更多的包装。
<强> app.js 强>
require(['module1'], function(mod) {
mod.loadPerson(function(person) {
document.getElementById("greeting").value = person.getPersonName();
});
});
<强> module1.js 强>
define(['jquery'], function($) {
return {
loadPerson : function(callback) {
$.get('values/person.json').done(function(data) {
_person = data;
callback({
getPersonName: function() { return _person.name; }
});
});
}
}
}
你也可以使用promises promises而不是简单的回调。