【Javascript】FileReaderの取得結果を変数に入れる


JavascriptのFileReaderは非同期的に実行され、onloadイベントの中で取得結果を処理するというのが一般的な使い方だと思います。

今回、このFileReaderの取得結果をonloadの中で処理するのではなく、グローバル変数に格納する方法について共有したいと思います。





通常のFileReaderの使い方

おそらく通常のFileReaderは下記のように記述すると思います。
Blob(またはFile)をdata URLに変換するリクエストをして、onloadイベントの中で結果を取得して処理をしていくというものですね。

onloadの中でしか続きを書けないという制限があります。

let blob = new Blob(["hoge"], {type: 'image/png'})

let reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = function() {
    dataUrl = reader.result

    //取得したdata URLに対する処理
    .
    .
    .
}




FileReaderの結果をグローバル変数に入れようとしてみる

FileReaderの結果をグローバル変数に入れようとしてみると、下記のようなコードを思いつきます。
しかしこれはうまく動きません。

dataUrl変数にはundefinedが入ってしまいます。

let blob = new Blob(["hoge"], {type: 'image/png'})

let dataUrl = ''
let reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = function() {
    dataUrl = reader.result
}

console.log(dataUrl)  //undefinedが入ってしまう




FileReaderの結果をグローバル変数に格納する正しいやり方

async/awaitPromiseを使うとFileReaderの結果をグローバル変数に格納することができます。

6行目はFileReaderのonloadresolveメソッド⇒Promiseが完了 という流れになります。
awaitでPromiseの処理を待っているので、7行目で結果を変数に格納できるということになります。

;(async function() {
    let blob = new Blob(["hoge"], {type: 'image/png'})
    
    let reader = new FileReader()
    reader.readAsDataURL(blob)
    await new Promise(resolve => reader.onload = () => resolve());
    dataUrl = reader.result
    
    console.log(dataUrl)  //data URLが入っている
})()


awaitasync関数の中でしか使えません。上記では最終行に()を付けることでasync関数を即時関数として実行しています。なのでawaitを使う可能性がある時はすべてのコードをasync即時関数で囲ってしまってもいいのではないかなと思います。(下記のようなイメージ)

;(async function() {
    //なにかしらの記述
    //なにかしらの記述
    //なにかしらの記述
    //なにかしらの記述

    let blob = new Blob(["hoge"], {type: 'image/png'})
    
    let reader = new FileReader()
    reader.readAsDataURL(blob)
    await new Promise(resolve => reader.onload = () => resolve());
    dataUrl = reader.result

    //なにかしらの記述
    //なにかしらの記述
    //なにかしらの記述
    //なにかしらの記述
})()




FileReaderの取得処理を関数としてまとめる

Promiseの記述が凡雑になるので、関数としてまとめてしまうと使いやすいです。

async function convert2DataUrl(blobOrFile) {
    let reader = new FileReader()
    reader.readAsDataURL(blobOrFile)
    await new Promise(resolve => reader.onload = () => resolve())
    return reader.result
}


下記のように使います。手続きのコードがとてもすっきりしました。

;(async function() {
    //なにかしらの記述
    //なにかしらの記述
    //なにかしらの記述
    //なにかしらの記述

    let blob = new Blob(["hoge"], {type: 'image/png'})
    let dataURL = await convert2DataUrl(blob)

    //なにかしらの記述
    //なにかしらの記述
    //なにかしらの記述
    //なにかしらの記述
})()

async function convert2DataUrl(blobOrFile) {
    let reader = new FileReader()
    reader.readAsDataURL(blobOrFile)
    await new Promise(resolve => reader.onload = () => resolve())
    return reader.result
}



下記の記事を参考にさせていただきました。
実例で学ぶPromise (2)




以上、FileReaderの取得結果を変数に入れる方法でした!

スポンサーリンク

You can subscribe by SNS

スポンサーリンク

コメントを残す

*