画像の読み込みをPromiseで制御する
画像を読み込んだタイミングで次の挙動に移って欲しい時があると思います。
そういった時にPromiseを使う事でJavaScript内で画像のロードタイミングに合わせて、Promiseを解消できる形にしました。
Promiseやasync/awaitに関しては、以下の記事にも書いているので、興味があれば合わせて読んでください。
読み込みを制御するとはどういうことか
例えば、プロフィール画像などを設定する時に、プレビュー画像というのが出ると思います。
そのプレビュー画像のところに表示させているのは、画像をbase64形式にしたもので、画像を文字として扱うためのものです。
そのプレビューを表示させるために、画像を設定し、読み込んだ(画像を認識した)後に、該当箇所にその画像のbase64の文字列を当てはめることでプレビューとして表示します。
この読み込むタイミングの後に何か処理を挟みたい、もしくは読み込んでbase64を当てはめた後に実行したい処理をする場合、base64を当てはめるまで待たせる必要があります。
この時にPromiseを使って、解決させるタイミングで次の処理にいけるようにしました。
読み込むタイミングはonloadで
imageが読み込まれる時にPromiseを解決します。
imageが読み込まれる時というのは、imgタグのsrcにbase64画像がセットされる時です。
つまり
$image.src = base64:XXXXXXXX
このようにして読み込んだ時ということですね。
この時の$image
は、実際のDOMでも、JavaScriptで作り出したImageでも同じです。
const image = new Image()
このimageへのsrc属性に対してロードが完了した時点でPromiseを解消します。
const imgLoad = () => {
const image = new Image()
image.crossOrigin = 'anonymous'
image.width = 500
image.height = 300
return new Promise(resolve => {
image.onload = () => {
resolve(image)
}
image.src = 'base64:XXXXXXXX'
})
}
onloadに画像のsrcが読み込まれたタイミングで実行する事を前もって、imageに仕込んでおいて
読み込みが完了するとonloadの処理が走るという流れになります。
この時、TypeScriptを使っていた場合、Promiseのジェネリクスはresolveで解消する時に渡されるデータ型になります。
文字列の場合
return Promise<string>(resolve => {
resolve('string')
})
エラーも制御できる
先ほどのonloadをerror発生イベントに変えるだけです。
const imgLoad = () => {
const image = new Image()
image.crossOrigin = 'anonymous'
image.width = 500
image.height = 300
return new Promise((resolve, reject) => {
image.onload = () => {
resolve(image)
}
image.onerror = (error) => {
reject(error)
}
image.src = 'base64:XXXXXXXX'
})
}
このロードを待つ事によって、画像に対してロードのタイミングで処理を挟む事もできますし
後続の処理を待たせる事もできます。
参考
Discussion