【2025革新型・高速USB3.0対応】 CD DVDドライブ 外付け 静音 DVDプレーヤー 外付けDVDドライブ USB3.0&Type-C両接続 読取/書込可 CDプレーヤー バスパワー駆動 外付けCDドライブ 軽量 薄型 光学ドライブ 外付け CDドライブ Mac PC パソコン Windows11対応 Windows10/8/7XP 外付け CD DVD ドライブ (ホワイト)
¥1,999 (2025年4月25日 13:05 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)
画像を複数枚jsで読み込む実装を行なっていたところ、
generosenninさんから「onloadよりimage.decodeを使った方がいいよ。」とアドバイスいただきました。
ただ、実際に実装するとなぜかうまくいかなかったので調査した結果をここに記します
for文で回しながら画像を取得する処理において、image.decodeを利用すると、下記のエラーが発生する。
これは特定の画像やタイミングで起きるものではなく、不定期のタイミングで発生する(ただ、必ずに近いレベルで発生した)
EncodingError: The source image cannot be decoded.
imagesフォルダに連番で1.png~30.pngを適当に配置する
HTMLを適当に作る
index.html
lang="en">
charset="UTF-8">
name="viewport" content="width=device-width, initial-scale=1.0">
Document
"main.js">
Javascript
main.js
for (let index = 0; index 30; index++) {
const img = new Image();
img.src = `./images/${index + 1}.jpeg`;
img
.decode()
.then(() => {
document.body.appendChild(img);
})
.catch((encodingError) => {
console.error(`画像 ${index + 1} のロード中にエラーが発生しました:`, encodingError);
});
}
これでindex.htmlを開くと該当のエラーの発生を確認できる。
同じことをimage.onloadでやるとエラーは発生しない。
main.js
for (let index = 0; index 30; index++) {
const img = new Image();
img.src = `./images/${index + 1}.jpeg`;
img
.onload = () => {
document.body.appendChild(img);
}
img.onerror = () => {
console.error(`画像 ${index + 1} のロード中にエラーが発生しました:`, encodingError);
}
}
ドキュメントをちゃんと読めば書いてありますが、
DOMに追加しても”安全になったとき”に解決されるプロミスな訳です。
for文で回している以上、decodeが安全性を確認する前に次のdecodeが実行されてしまい、安全性を解決できずにデコードできない画像が生まれてしまうことが原因でこの問題が起きているようです。
※あくまで私の意見なので、違ったら教えてください。
画像単体の読み込みや、逐次的に画像を読み込む場合(ボタンを押したらロードされる仕組みなど)であれば、onloadよりも優先して利用すべきです。
例えば下記のような仕組みで利用する分には問題ありません。
main.js
let currentImageIndex = 0;
const totalImages = 30;
// 次の画像を読み込む関数
function loadNextImage() {
if (currentImageIndex >= totalImages) {
console.log('すべての画像がロードされました');
return;
}
const img = new Image();
img.src = `./images/${currentImageIndex + 1}.jpeg`;
img.style.width = '200px';
img.style.height = 'auto';
img.alt = `画像 ${currentImageIndex + 1}`;
// 画像をデコードして表示
img.decode()
.then(() => {
document.body.appendChild(img);
console.log(`画像 ${currentImageIndex + 1} をロードしました`);
currentImageIndex++;
})
.catch((encodingError) => {
console.error(`画像 ${currentImageIndex + 1} のロード中にエラーが発生しました:`, encodingError);
currentImageIndex++; // エラーが発生した場合も次の画像に進む
});
}
// ページ読み込み時に最初の画像をロード
document.addEventListener('DOMContentLoaded', () => {
// ボタンを作成して画面に追加
const loadButton = document.createElement('button');
loadButton.textContent = '次の画像を読み込む';
loadButton.style.display = 'block';
loadButton.style.margin = '10px 0';
loadButton.addEventListener('click', loadNextImage);
document.body.appendChild(loadButton);
// 最初の画像を自動的にロード
loadNextImage();
});
やりたいことに応じて、decodeとonloadを適切に使い分けるのが良さそう。
基本的にはdecodeを使いつつ、大量の画像を一気に呼ぶ分にはonloadでやる方針で実装できると良いですね〜