Подтвердить что ты не робот

Чтение файла синхронно в Javascript

Я хотел бы прочитать файл и преобразовать его в кодировку base64 с использованием объекта FileReader. Здесь код, который я использую:

    var reader = new FileReader();
    reader.onloadend = function(evt) {  
        // file is loaded
        result_base64 = evt.target.result; 
    };
    reader.readAsDataURL(file); 


Но в этом случае я получаю результат преобразования в обработчике события (событие onLoadEnd). Мне нужен синхронный метод. Есть ли способ, которым метод readAsDataURL может напрямую возвращать значение переменной "result_base64"?

Спасибо

4b9b3361

Ответ 1

Синхронные задачи (блокировка), как правило, плохие. Если нет реальной причины сделать это асинхронно, я настоятельно рекомендую вам использовать обратный вызов события.

Представьте, что ваш файл поврежден и HTML5 api cant читает, он не даст вам результат. Это нарушит ваш код и заблокирует сайт. Или кто-то может выбрать 10GB файл, который заморозит вашу HTML-страницу, пока файл не будет полностью загружен. С помощью этого асинхронного обработчика событий вы сможете поймать возможные ошибки.

Чтобы обойти ограничения с обратными вызовами, я использую простой трюк:

var ready = false;
var result = '';

var check = function() {
    if (ready === true) {
         // do what you want with the result variable
         return;
    }
    setTimeout(check, 1000);
}

check();

var reader = new FileReader();
reader.onloadend = function(evt) {
    // file is loaded
    result = evt.target.result;

    ready = true;
};
reader.readAsDataURL(file);

функция проверки, проверяет каждую секунду, если для переменной готового флага установлено значение true. Если это так, вы можете быть уверены, что результат будет доступен.

Это может быть не самая лучшая практика, но я сделал webapp, используя эту технику примерно 30 раз с более чем 10 setTimeouts одновременно, и до сих пор не испытывал проблем.

Ответ 2

Чтобы прочитать содержимое файла синхронно, используйте fs.readFileSync

var fs = require('fs');
var content = fs.readFileSync('myfilename');
console.log(content);

fs.createReadStream создает ReadStream.

Ответ 3

Вы можете использовать стандартную FileReaderSync, которая является более простой, синхронной, блокирующей версией API FileReader, аналогичной той, что вы уже используете:

let reader = new FileReaderSync();
let result_base64 = reader.readAsDataURL(file); 

console.log(result_base64); // aGV5IHRoZXJl...

Имейте в виду, что это доступно только в рабочих потоках по очевидным причинам.


Если вам нужно решение для основного потока, который "читает как" синхронный API, вы можете обернуть async FileReader в обещание и использовать асинхронные функции (вам может понадобиться выполнить транспиляцию):

async function readFileAsDataURL(file) {
    let result_base64 = await new Promise((resolve) => {
        let fileReader = new FileReader();
        fileReader.onload = (e) => resolve(fileReader.result);
        fileReader.readAsDataURL(file);
    });

    console.log(result_base64); // aGV5IHRoZXJl...

    return result_base64;
}

Ответ 4

В Node.js, используйте execSync из child_process и попросите его прочитать его синхронно. Перенаправить вывод этого дочернего процесса в родительский.

// Don't forget to use your favorite encoding in toString()
var execSync = require('child_process').execSync;
var fileContents = execSync('cat path/to/file.txt', {stdio: "pipe"}).toString();

Я с радостью соглашусь с вашей номинацией на награду UUOC.;)

Ответ 5

Позднее в бизнесе, но может быть, это поможет кому-то. Мы можем просто взять бой за пределы комнаты.

var file = $('#myfile')[0].files[0];

var reader = new FileReader();
reader.onload = function(progressEvent) {
        //console.log(this.result);
        handle(this.result);
};
reader.readAsText(file);

function handle(temp_lines) {
    var inputLines=new Array();
    var lines = temp_lines.split('\n');

    for(var line = 0; line < lines.length; line++) {
        console.log(lines[line]);
        inputLines[line]=lines[line];
    }
}