Как сохранить результат считывания файлов js в переменную для дальнейшего использования? - PullRequest
1 голос
/ 03 апреля 2019

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

Все работает в среде Angularjs (1.7), отсюда и синтаксис фрагмента. Предполагается использовать для отображения прочитанных данных на карте открытых слоев.

    this.jsonSelected = function(newFile) {
        let reader = new FileReader();
        let result = 'empty';
        reader.readAsText(newFile);
        reader.onload = function(e) {
            result = e.target.result;
            console.log('in onload', result);
            this.result = e.target.result;
        };
        console.log(this.result);
    };

    this.test = function() {
        console.log(this.file);
    }

Я ожидаю, что код выйдет из содержимого файла дважды. Однажды на "console.log ('в onload', результат);" и в другой раз на "console.log (this. result);". Первый работает как положено. но почему-то второй не получится. Также порядок в консоли переворачивается, console.log (this. Result) предшествует журналу загрузки, как вы можете видеть на этом снимке экрана консоли .

Я пробовал несколько вариантов, меняя названия, меняя это. и так далее, но безрезультатно. Вот почему я считаю, что я испортил обработку асинхронных данных. Также на скриншоте, а точнее на строках из журналов, указана какая-то проблема синхронизации.

Ответы [ 2 ]

1 голос
/ 03 апреля 2019

После некоторых дальнейших исследований и проб и ошибок я получил кое-что для работы. Код теперь выглядит так:

function readFile(newFile) {
    return $q(function(resolve, reject) {
        let reader = new FileReader();
        reader.onload = function(event) {
            resolve(event.target.result);
        };
        reader.onerror = function(event) {
            reject(event);
        };
        reader.readAsText(newFile);
    });
}

this.jsonSelected = function(newFile) {
    readFile(newFile).then(function(data) {
        console.log(data);
        set$scopeFile(data);
    }, function(errData) {

    });
};

Спасибо, Бен, ты привел меня на правильный путь, я был так сосредоточен на поиске способа справиться с асинхронными частями, что я просто упустил из виду проблемы с областями видимости. Если у кого-нибудь есть какие-то "защищенные от дурака" документы по асинхронному JS, я был бы очень признателен, так как у меня возникли проблемы, когда я обдумывал эту тему.

Я использовал встроенный в $ q сервис angularjs, чтобы превратить весь процесс чтения в обещание. Который затем может быть прикован цепью с .then.

0 голосов
/ 03 апреля 2019

Это классический асинхронный + обзорный вопрос ...

Сначала вы используете неправильную область. this внутри reader.onload отличается от this с console.log(this.result);.
Вам следует либо bind onload, либо использовать функции стрелок.

Далее onload является асинхронным, поэтому он будет работать ПОСЛЕ console.log(this.result);.
Один из способов справиться с этим - использовать Promises ($q в AngularJS). Что-то вроде:

const deferred = $q.defer(); 
deferred.then((data) => { console.log('result', data); });
reader.onload = function(e) {
     result = e.target.result;
     console.log('in onload', result);
     deferred.promise.resolve(e.target.result);
};
...