javascript、异步、等待:can';t将值提取到类变量中
tldr如何从javascript、异步、等待:can';t将值提取到类变量中,javascript,async-await,Javascript,Async Await,tldr如何从Promise 我太笨了,以至于不能用javascript来使用async/await,这让我大吃一惊。当然有很多例子和博客文章,但它们是“then”将结果只放在console.log中,这是我不需要的 我的用例非常简单,我希望使用fetch从json加载翻译(如果还没有加载),然后使用函数translate返回翻译后的值 我想如果我使用然后,那么执行就会暂停,直到承诺解决或失败 class Test { constructor() { } /**
Promise
我太笨了,以至于不能用javascript来使用async/await
,这让我大吃一惊。当然有很多例子和博客文章,但它们是“then”
将结果只放在console.log中,这是我不需要的
我的用例非常简单,我希望使用fetch从json加载翻译(如果还没有加载),然后使用函数translate
返回翻译后的值
我想如果我使用然后
,那么执行就会暂停,直到承诺
解决或失败
class Test {
constructor() {
}
/**
* Loads translations
*/
async _loadTranslations() {
console.log("Loading tanslations");
let response = await fetch('data.json');
let json = await response.json();
return json;
};
translate(key, language) {
if(!this.translation){
this._loadTranslations().then(data =>{
console.log("data is loaded!", data);
this.translation = data;});
}
return this.translations[language][key];
}
}
console.log("translation",new Test().translate("MEGA_MENU_CMD","de-DE"))
但它总是记录未定义的翻译
我不想要这样的东西
new Test()._loadTranslations().then(r => console.log("result",r))
因为我想在模板中使用translate函数,而不想在所有模板中使用
Edit我不知道如何使用fetch
从API获取数据并将其设置为类的模型。在我看来,then
s和callback
s做了不同的事情。或者,实例化类、从API加载数据然后处理这些数据的正确方法是什么
第二次编辑:
事实上,我只想创建一个TranslationMixin并加载一次翻译。然后在我的页面中(我正在玩Polymer),我想使用返回html'${this.translate(“de de”,“propertyX”}“
这就是为什么我不想要承诺,而只想要简单的字符串。事实上,翻译应该在构建过程中加载并完成。但是由于fetch
返回Promise
我被Promise
卡住了,无法获取值(#叹气)。因此,我可能只坚持常规的XMLHttpRequest
。您需要等到翻译完成。最简单的方法是将翻译
也设置为异步函数。这将返回一个承诺,您可以在then()
中获得翻译:
类测试{
构造函数(){
}
/**
*加载翻译
*/
异步loadTranslations(){
控制台日志(“加载日志”);
this.translation=“一些翻译”
返回此文件。翻译;
};
异步翻译(键、语言){
如果(!this.translation){
返回此值。_loadTranslations()。然后(数据=>{
log(“数据已加载!”,数据);
返回数据;});
}
返回此文件。翻译;
}
}
新测试().translate(“MEGA_MENU_CMD”,“de de de”)
。然后(translate=>console.log(translate))
如果需要,还必须将translate异步化。
因此,您也需要使用async并等待该函数
因为他实际上会在_loadTranslations()中执行您期望的操作,他会等待结果,但由于调用它的函数不是异步的,所以他会一直执行所有操作直到结束!
我希望这会有所帮助。这是您最初寻找的异步/等待解决方案
translate(key, language){
return this.translation
? this.translation[language][key]
: this._loadTranslations()
}
由于还需要等待console.log,并且由于await
只能在异步函数中,因此可以执行以下操作
(async()=>{
console.log("translation", await new Test().translate("MEGA_MENU_CMD","de-DE"))
})()
解释
函数translate
返回此操作的结果。_loadTranslations()
即Promise
。然后,console.log语句等待该承诺并在其实现后输出,即从data.JSON获得JSON
如何正确地实例化类,从API加载数据,然后处理这些数据
在实例化类之前加载数据,然后实例可以同步使用它
在创建实例之前,您应该在静态方法中加载翻译,这样您就不必在translate
方法中等待它们:
class Test {
constructor(t) {
this.translations = t;
}
/**
* Loads translations
*/
static async fromLoadedTranslations() {
console.log("Loading tanslations");
let response = await fetch('data.json');
let json = await response.json();
console.log("data is loaded!", data);
return new this(json);
}
translate(key, language) {
return this.translations[language][key];
}
}
无法异步加载数据而不等待它(使用then
或wait
)某处。由于翻译
依赖于\u loadTranslations
,这是异步的,它也必须是异步的,因此您必须使用异步/等待
或遵循承诺方法。类似这样的内容应该会给您一个提示:是的,我知道。但我想使用de>translate
在某个模板中运行,我想在那里看到值,而不是承诺。但我会检查zero298注释中的链接。@FrankD“在某个模板中”是什么意思?你是在使用外部框架还是什么?有另一种可能的方法来解决这个问题,那就是注册一个事件(类似于“TranslationLoaded”事件),这允许您避免使用承诺,因为一旦事件触发,将加载翻译。我想创建一个TranslationMixin
,在我的页面中,我想使用返回html'${this.translate(“de de”,“propertyX”}“
这就是为什么我不想要一个Promise
而只想要一个普通字符串。事实上,翻译应该在构建过程中加载并完成。但是由于fetch
返回一个Promise
我被承诺卡住了,无法获得值(#叹气)。谢谢,如前所述,我不想将其打印到控制台。我知道这很好。我只需要翻译中的纯字符串值,不需要承诺。我想在其他类中使用翻译后的值,在那里我不想使用承诺,但要使用纯字符串。@FrankD得到了它。但看看它是怎样的。Javascript是单线程的。Bu我们不想让它从服务器获取一个文件-data.json。因此,当它执行此操作时,浏览器不能只等待它。这就是为什么所有这些驱动机制都存在的原因。将其视为按钮单击,当按钮单击发生时,会调用一个事件处理程序函数-浏览器
Test.fromLoadedTranslations().then(test => {
console.log("translation", test.translate("MEGA_MENU_CMD","de-DE"));
// or pass `test` to your polymer template
});
(async function() {
const test = await Test.fromLoadedTranslations();
console.log("translation", test.translate("MEGA_MENU_CMD","de-DE"));
// or pass `test` to your polymer template
}());