web-dev-qa-db-ja.com

Javascriptでファイルを同期的に読み取る

FileReaderオブジェクトを使用して、ファイルを読み取り、base64でエンコードされた文字列に変換したいと思います。私が使用するコードは次のとおりです。

 
 var reader = new FileReader(); 
 reader.onloadend = function(evt){
 //ファイルがロードされます
 result_base64 = evt .target.result; 
}; 
 reader.readAsDataURL(file); 
 
 

ただし、この場合、イベントハンドラー(onLoadEndイベント)で変換の結果を取得します。同期方式が欲しいのですが。 「readAsDataURL」メソッドが「result_base64」変数の値を直接返すことができる方法はありますか?

ありがとう

33
Laila

同期タスク(ブロッキング)は一般に悪いです。非同期的に行う理由が特にない場合は、イベントコールバックを使用することを強くお勧めします。

ファイルが壊れていて、HTML5 APIが読み取れないと想像してみてください。結果は得られません。コードが破損し、サイトがブロックされます。または、誰かが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);

チェック機能は、readyフラグ変数がtrueに設定されているかどうかを毎秒チェックします。その場合、結果が利用可能であることを確認できます。

そうするのはベストプラクティスではないかもしれませんが、このテクニックを使用して、同時に10回以上のsetTimeoutsで約30回webappを作成し、今まで問題はありませんでした。

17
David Fariña

標準の FileReaderSync を使用できます。これは、既に使用しているものと同様に、FileReader APIのより単純で同期的なブロッキングバージョンです。

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

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

ただし、これは明らかな理由により、ワーカースレッドでのみ使用できることに注意してください。


同期APIの「ように見える」メインスレッドのソリューションが必要な場合は、約束で非同期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;
}
2
John Weisz

ファイルの内容を同期的に読み取るには、 fs.readFileSync を使用します

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

fs.createReadStreamReadStream を作成します。

0
Jonathan Thurft