javascript, async, await: невозможно извлечь значение в переменную класса - PullRequest
0 голосов
/ 10 сентября 2018

tldr Как мне установить переменную класса из Promise

Я бьюсь головой, потому что я слишком глуп, чтобы использовать async/await с javascript. Конечно, есть множество примеров и постов в блогах, но они '1007 * приводят результаты только в console.log, что мне не нужно.

Мой вариант использования очень прост, я хочу загрузить переводы из json, используя fetch (если они еще не были загружены), а затем вернуть переведенное значение с помощью функции translate.

Я подумал, что если я использую then, то выполнение приостанавливается до тех пор, пока Promise не разрешится или не произойдет сбой.

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"))

Но он всегда записывает translation undefined.

Я не хочу что-то вроде

  new Test()._loadTranslations().then(r => console.log("result",r))

, поскольку я хочу использовать функцию перевода в шаблонах, и я не хочу использовать .then во всех моих шаблонах.

Редактировать Я не понимаю, как я могу использовать fetch для получения данных из API и установки их в качестве модели класса. then s и callback s, по моему мнению, делают разные вещи. Или как правильно создать экземпляр класса, загрузить данные из API и затем работать с этими данными?

2-е редактирование :

На самом деле, я просто хочу создать TranslationMixin и загрузить переводы один раз. Затем на своей странице (я играю с Polymer) я хочу использовать return html '<div>${this.translate("de-De","propertyX"}<div>', и поэтому я не хочу обещание, а просто простую строку. На самом деле перевод должен быть загружен во время строительства и сделано. Но когда fetch возвращает Promise, я застрял с Promise и не смог получить значение (#sigh). Так что, вероятно, я придерживаюсь обычного XMLHttpRequest ...

Ответы [ 4 ]

0 голосов
/ 11 сентября 2018

как правильно создать экземпляр класса, загрузить данные из 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];
    }
}

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
}());

Нет способа загрузить данные асинхронно и не ждать их где-либо (используя then или await).

0 голосов
/ 10 сентября 2018

Если вы хотите, вы должны поставить свой перевод Asynchronous aswell. Так что вам нужно использовать async и ожидать этой функции тоже.

Потому что он на самом деле будет делать то, что вы ожидаете в _loadTranslations (), и он будет ждать результата, но поскольку вызывающая его функция не асинхронна, он сделает все до конца! Надеюсь, это поможет.

0 голосов
/ 10 сентября 2018

Это решение для асинхронного ожидания / ожидания, которое вы искали.

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 возвращает результат this._loadTranslations(), равный Promise. Затем оператор console.log ожидает , что Promise и выводит, как только он будет выполнен, то есть, когда у вас есть JSON из data.json.

0 голосов
/ 10 сентября 2018

Вам нужно дождаться окончания перевода.Самый простой способ сделать это - также сделать translate асинхронной функцией.Это вернет обещание, и вы можете получить перевод в then():

class Test {

    constructor() {
    }

    /**
     * Loads translations
     */
    async _loadTranslations() {
        console.log("Loading tanslations");
        this.translation = "some translation"
        return this.translation;
    };

    async translate(key, language) {
      if(!this.translation){
         return this._loadTranslations().then(data =>{
            console.log("data is loaded!", data);
            return  data;});
       }
       return this.translation;
    }

}
new Test().translate("MEGA_MENU_CMD","de-DE")
.then(translate => console.log(translate))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...