javascript、异步、等待:can';t将值提取到类变量中

javascript、异步、等待:can';t将值提取到类变量中,javascript,async-await,Javascript,Async Await,tldr如何从Promise 我太笨了,以至于不能用javascript来使用async/await,这让我大吃一惊。当然有很多例子和博客文章,但它们是“then”将结果只放在console.log中,这是我不需要的 我的用例非常简单,我希望使用fetch从json加载翻译(如果还没有加载),然后使用函数translate返回翻译后的值 我想如果我使用然后,那么执行就会暂停,直到承诺解决或失败 class Test { constructor() { } /**

tldr如何从
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
}());