質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.30%
Chrome

Google Chromeは携帯、テレビ、デスクトップなどの様々なプラットフォームで利用できるウェブブラウザです。Googleが開発したもので、Blink (レンダリングエンジン) とアプリケーションフレームワークを使用しています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1722閲覧

Chrome拡張APIの「chrome.downloads.onDeterminingFilename」に登録したリスナーの挙動がわからない

aki3

総合スコア10

Chrome

Google Chromeは携帯、テレビ、デスクトップなどの様々なプラットフォームで利用できるウェブブラウザです。Googleが開発したもので、Blink (レンダリングエンジン) とアプリケーションフレームワークを使用しています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2022/02/17 07:15

編集2022/02/17 07:16

onDeterminingFilenameのAPIリファレンスには以下のような記述があります。

Each extension may not register more than one listener for this event.

この記述を和訳すると「各拡張機能は、このイベントにたいして複数のリスナーを登録することができません」という意味になると思います。しかし、実際には、複数のリスナーを登録できます。

js

1// 例1 2const listener = (item, suggset) => { 3 return suggset() 4} 5 6chrome.downloads.onDeterminingFilename.addListener(listener) 7chrome.downloads.onDeterminingFilename.addListener(listener)

ただし、以下のケースではエラーが発生します。

js

1// 例2 2const listener1 = (item, suggset) => { 3 return suggset() 4} 5const listener2 = (item, suggset) => { 6 return suggset() 7} 8 9chrome.downloads.onDeterminingFilename.addListener(listener1) 10chrome.downloads.onDeterminingFilename.addListener(listener2) // さっきと違う関数をリスナーとして登録する

上のコードでは、1度目に登録したリスナーと、2度目に登録したリスナーが違います。この場合、画像をダウンロードしたとき、以下のようなエラーが発生します。

suggestCallback may not be called more than once.

例1と例2は同様に2つのリスナーを登録しているわけですが、例2のコードはエラーが発生します。なぜこのような挙動になるのかしりたいです。

なぜこのような挙動になるのか知りたい理由

複数の画像をまとめてDLする拡張機能をつくっています。

その拡張機能の中で「同時にダウンロードしている画像の数だけonDeterminingFilenameにリスナーを登録する」というような処理があります。

その拡張機能のコードを抜粋したものがこちらです。長くてすみません。。。

js

1import { extractExtensionFromFilename } from "../utils" 2import TaskQueue from "./task-queue" 3 4export default class DownloadTask { 5 constructor({ urls, directory, concurrency }) { 6 this.urls = urls 7 this.directory = directory 8 this.queue = new TaskQueue(concurrency) 9 } 10 11 start() { 12 for (const url of this.urls) { 13 this.queue.push(async () => { 14 await this.download(url) 15 }) 16 } 17 } 18 19 download(url) { 20 return new Promise((resolve, reject) => { 21 chrome.downloads.download({ url }, id => { 22 const onChanged = item => { 23 if (item.id !== id) { 24 return 25 } 26 27 if (item.error) { 28 // todo: handle error 29 finish() 30 return reject() 31 } 32 33 if (item.state?.current === 'complete') { 34 finish() 35 return resolve() 36 } 37 } 38 39 const onDeterminingFilename = (item, suggest) => { 40 if (item.id !== id) { 41 return 42 } 43 44 const ext = extractExtensionFromFilename(item.filename) 45 const index = this.urls.indexOf(url) 46 const filename = ext 47 ? `${this.directory}/${index}.${ext}` 48 : `${this.directory}/${index}` 49 return suggest({ filename }) 50 } 51 52 const finish = () => { 53 chrome.downloads.onChanged.removeListener(onChanged) 54 chrome.downloads.onDeterminingFilename.removeListener(onDeterminingFilename) 55 } 56 57 chrome.downloads.onChanged.addListener(onChanged) 58 chrome.downloads.onDeterminingFilename.addListener(onDeterminingFilename) 59 }) 60 }) 61 } 62}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

自己解決しました。同じ関数は1つしか登録できないようです。

投稿2022/02/17 07:20

aki3

総合スコア10

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問