невозможно установить правильную область видимости для переменной в обещании JavaScript - PullRequest
0 голосов
/ 30 октября 2018

Я столкнулся со странной проблемой, когда новая переменная создается в локальной области, даже если она определена снаружи,

из приведенного ниже кода

после того, как я вызываю buildMeta () и проверяю содержимое «данных», оно всегда пустое подразумевая, что он вообще не изменяется, даже если я специально нацелил «that.data», где он ссылается на объект класса.

Буду признателен, если кто-нибудь укажет, что я делаю неправильно.

class meta {

    constructor(files) {
        if(!files) throw Error("files not specified");
        this.data = {};
        this.ls = files;
    }

  buildMeta() {
        var that = this;
        for(let i = 0; i < that.ls.length; i++) {

            mm.parseFile(that.ls[i]).then(x => {
                var info = x.common;
                that.data[info.artist] = "test";
            }).catch((x) => { 
               console.log(x);    
            });
       }

    }
 }
const mm = new meta(indexer); // indexer is an array of file paths
mm.buildMeta();
console.log(mm.data);

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Здесь вы смешиваете синхронизацию с асинхронным кодом. Цикл for не будет ждать разрешения parseFile. Вы можете использовать Promise.all для заполнения данных при разборе файлов.

// Class names should be written using a capital letter 
class Meta {
    ...
    buildMeta() {
     // You don't need this assignment since you're using arrow functions
    // var that = this;
    const promises = this.ls.map(filePath => mm.parseFile(filePath));
    return Promise.all(promises).then(resolvedPromises => {
        resolvedPromises.map(({ parsedFile }) => {
            this.data[parsedFile.common.artist] = "test";
       });
       return this.data;
    }).catch(console.error);
}

...

const mm = new meta(indexer); // indexer is an array of file paths
mm.buildMeta().then(data => {console.log(data)});

Надеюсь, это поможет.

0 голосов
/ 30 октября 2018

Вы регистрируетесь mm.data до завершения parseFile. Ваш код подразумевает, что он возвращает обещание, поэтому ваша вставка в that.data произойдет после того, как вы выполните console.log(mm.data).

Вам нужно вернуть обещание от buildMeta, чтобы вы могли сделать ...

const mm = new meta(indexer);
mm.buildMeta().then(() => {
    console.log(mm.data);
})

Вот buildMeta, который должен делать то, что вам нужно. Это возвращает обещание, которое ждет, пока все вызовы parseFile выполнят свою работу и обновят this.data ...

buildMeta() {
    return Promise.all(this.ls.map(f => mm.parseFile(f).then(x => {
        var info = x.common;
        this.data[info.artist] = "test";
    })))
}
...