2013-06-12 1 views
19

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

 

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


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

Thanks

+3

* «Я хотел бы синхронный метод». * Любая конкретная причина, почему? Я не думаю, что это возможно. –

+0

У firefox есть/есть метод file.getAsDataURL(), но он устарел и был единственной версией синхронизации любого браузера afaik. – dandavis

+0

Я хранил пути в локальной базе данных хранилища, мне нужно отправить изображения на сервер (с петлей на всех изображениях, поэтому мне нужен синхронный метод). Я хотел бы избежать хранения строк base64 в базе данных, чтобы не превышать ограничение локального хранения ... – Laila

ответ

10

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

Представьте, что ваш файл поврежден и 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); 

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

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

+0

У меня был подобный трюк, но он сломался, как только я вставил код в цикл. Я, наконец, использовал методы обратных вызовов в сочетании с закрытием, чтобы узнать, когда цикл заканчивается. – Laila

+1

Имеет ту же проблему, что и я, чтобы передать переменные параметра в обратный вызов. Цель состояла в том, чтобы разделить файл на куски, чтобы я мог отправить его на сервер. Закрытие - это замечательная вещь, которую когда-то понимали. –

+0

https://stackoverflow.com/a/46832928/851951 Этот подход хорош, но он остается асинхронным. – Dani

-3

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

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]; 
    } 
} 
+4

Мне непонятно, как это синхронно. – Nathan

+0

Это не так. Это асинхронный способ сделать это. – trinalbadger587

0

В 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. ;)