我有一个简单的对象可以在某些时间工作,但不是其他的,我试图找出原因:
var Language = {
language:"fr",
words:{
},
setLanguage: function(lang) {
Language.language=lang;
},
loadFile: function(file) {
//get the json object
$.getJSON("/" + Language.language + "/lang/" + file, function( data ) {
//go through each item in the json object and add it to the
$.each( data, function( key, val ) {
console.log(key+":"+val);
Language.words[key]=val; //add the word
});
});
},
getWord: function(word) {
return Language.words[word];
}
};
执行顺序似乎是随机的。在下面的两个示例中,我看到了alert
,然后是console
填充。
1)
<script src="/common/js/jquery.min.js"></script>
<script src="/common/js/language.js"></script>
<script>
$(document).ready(function(){
Language.setLanguage("en");
Language.loadFile("main.json");
alert(Language.getWord('lang'));
});
</script>
2)
<script src="/common/js/jquery.min.js"></script>
<script src="/common/js/language.js"></script>
<script>
Language.setLanguage("en");
Language.loadFile("main.json");
$(document).ready(function(){
alert(Language.getWord('lang'));
});
</script>
我最近无法重现,但我已经得到了#34;英语&#34;返回一次,这是JSON
文件中索引为lang的值。如何确保在脚本开头填充对象,以便加载的任何其他脚本都可以使用它。
答案 0 :(得分:1)
我们发现自己处于一个似乎沿着我们称之为“时间”的维度前进的宇宙中。我们真的不明白时间是什么,但我们已经开发了抽象和词汇,让我们推理和讨论它:“过去”,“现在”,“未来”,“之前”,“之后”。
我们构建的计算机系统 - 越来越多 - 将时间作为一个重要方面。某些事情将在未来发生。然后,在最终发生的第一件事之后,还需要发生其他事情。这是称为“异步性”的基本概念。在我们日益网络化的世界中,最常见的异步性情况是等待一些远程系统响应某些请求。
考虑一个例子。你打电话给送奶工并点一些牛奶。当它到来时,你想把它放在咖啡里。你现在不能把牛奶放在你的咖啡里,因为它还没有。在将它放入咖啡之前,你必须等待它。换句话说,以下内容不起作用:
var milk = order_milk();
put_in_coffee(milk);
因为JS无法知道在order_milk
执行put_in_coffee
之前需要等待才能完成。换句话说,它不知道order_milk
是异步 - 在未来某个时间之前不会产生牛奶。 JS和其他声明性语言在不等待的情况下执行一个接一个的语句。
这个问题的经典JS方法,利用JS支持函数作为可以传递的第一类对象的事实,是将函数作为参数传递给异步请求,然后它将在调用时调用它在未来的某个时候完成了它的任务。这就是“回调”方法。它看起来像这样:
order_milk(put_in_coffee);
order_milk
开始,订购牛奶,然后,只有当它到达时,才会调用put_in_coffee
。
这种回调方法的问题在于,当处理更长的事件序列时,它会迅速变得难以处理。例如,假设我想等待将牛奶放入咖啡中,然后再进行第三步,即喝咖啡。我最终需要写这样的东西:
order_milk(function(milk) { put_in_coffee(milk, drink_coffee); }
我要将牛奶放入put_in_coffee
,并将牛奶放入后执行动作(drink_coffee
)。这样的代码变得很难写,并且阅读和调试。
Marcos已经提供了一个如何针对您的特定问题使用回调模式的示例。
这是“承诺”概念的动机,“承诺”是一种特殊类型的价值,代表某种未来或异步结果。它可以代表已经发生的事情,或者将来会发生的事情,或者根本不会发生的事情。 Promise有一个名为then
的方法,当promise表示的结果已经实现时,你传递一个动作。
对于我们的牛奶和咖啡,我们设计order_milk
以返回牛奶到达的承诺,然后将put_in_coffee
指定为then
操作,如下所示:
order_milk() . then(put_in_coffee)
这样做的一个优点是我们可以将它们串在一起以创建未来发生的序列(“链接”):
order_milk() . then(put_in_coffee) . then(drink_coffee)
让我们对您的特定问题应用承诺。我们将修改loadFile
以返回承诺:
loadFile: function(file) {
//get the json object
return $.getJSON("/" + Language.language + "/lang/" + file, function( data ) {
//go through each item in the json object and add it to the
$.each( data, function( key, val ) {
console.log(key+":"+val);
Language.words[key]=val; //add the word
});
});
},
实际上,我们所做的就是在return
的调用中添加$.getJSON
。这是有效的,因为jQuery的$.getJSON
已经返回了一种类似承诺的东西。 (实际上,在没有详细说明的情况下,我们更愿意包装此调用以返回真正的承诺,或者使用$.getJSON
的替代方法来执行此操作。)现在,如果我们要加载文件并等待它完成然后做一些事情,我们可以简单地说
Language.loadFile() . then(do_something)
例如,
Language.loadFile() .
then(function() { alert(Language.getWord('lang')); });
使用promises时,我们最终会将大量函数传递给then
,因此使用更紧凑的ES6样式箭头函数通常会有所帮助:
Language.loadFile() . then(() => alert(Language.getWord('lang')));
但是,对于必须以同步方式编写代码以及异步时采用完全不同的方式,仍然存在一些模糊不满的问题。对于同步,我们写
a();
b();
但如果a
是异步的,我们必须写承诺
a() . then(b);
上面,我们说“JS无法知道它需要等待第一次调用才能执行第二次”。如果 以某种方式告诉JS,那会不会很好。事实证明,有一个await
关键字,用于称为“异步”函数的特殊类型的函数中。此功能是即将推出的ES版本的一部分,但已经在诸如Babel之类的转发器中提供了正确的预设。这允许我们简单地写
async function morning_routine() {
var milk = await order_milk();
var coffee = await put_in_coffee(milk);
await drink(coffee);
}
在您的情况下,您可以编写类似
的内容async function foo() {
await Language.loadFile("main.json");
Language.getWord('lang');
}
答案 1 :(得分:0)
问题是$.getJSON
是异步执行的,这就是你获得这种行为的原因。
将回调传递给你的loadFile函数,然后使用那里的其余代码。
<强> language.js 强>
loadFile: function(file, callback) {
//get the json object
$.getJSON("/" + Language.language + "/lang/" + file, function( data ) {
//go through each item in the json object and add it to the
$.each( data, function( key, val ) {
console.log(key+":"+val);
Language.words[key]=val; //add the word
});
callback(); //Callback function
});
},
<强> HTML 强>
<script>
$(document).ready(function(){
Language.setLanguage("en");
Language.loadFile("main.json", function(){
alert(Language.getWord('lang'));
});
});
</script>