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

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

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

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

Q&A

解決済

2回答

2104閲覧

promiseチェーンをfor文でループさせたい

jesuissuyaa

総合スコア18

JavaScript

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

0グッド

0クリップ

投稿2019/06/27 06:59

編集2019/06/27 07:36

PDF.jsでPDFビュワーを作っています。

PDF1ページを読み込む処理は非同期処理で書かれていて、これをドキュメント全てのページを表示できるように書き換えたいです。

元のコード:

javascript

1pdfDocument.getPage(i) 2.then(function (p) { 3 page = p; 4 console.log('page #: ' + i); 5 viewport = page.getViewport({ scale: PAGE_SCALE, }); 6 return page.getTextContent() 7}).then(function (textContent) { 8 // building SVG and adding that to the DOM 9 var svg = buildSVG(viewport, textContent); 10 document.getElementById('pageContainer').appendChild(svg); 11});

for文で回してうまくいかなかったコード:

javascript

1let promise = Promise.resolve(); 2for (let i = 1; i <= pdfDocument.numPages; i++) { 3 promise.then(function () { 4 pdfDocument.getPage(i) 5 .then(function (p) { 6 page = p; 7 console.log('page #: ' + i); 8 viewport = page.getViewport({ scale: PAGE_SCALE, }); 9 return page.getTextContent() 10 }).then(function (textContent) { 11 // building SVG and adding that to the DOM 12 var svg = buildSVG(viewport, textContent); 13 document.getElementById('pageContainer').appendChild(svg); 14 }); 15 }) 16}

コンソールに出力される順番は1, 2, 3, ... となりましたが、ページのロードは以前として順番通りになりません。
おそらく二つめのthenがあることが原因だと思いますが、どのように ...then()... で繋がっているコードをループで回せるように書き換えたらいいかわかりません。

追記: async/awaitを使って書いてみましたが、結果は変わりませんでした

javascript

1async function renderPage(pageNum) { 2 var page = await pdfDocument.getPage(pageNum); 3 console.log('page #: ' + pageNum); 4 viewport = page.getViewport({ scale: PAGE_SCALE, }); 5 var textContent = await page.getTextContent(); 6 var svg = buildSVG(viewport, textContent); 7 document.getElementById('pageContainer').appendChild(svg); 8 } 9 10 for (let i = 1; i <= pdfDocument.numPages; i++) { 11 renderPage(i); 12 } 13}

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

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

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

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

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

Lhankor_Mhy

2019/06/27 07:07

await を使ってもいいのですか?
jesuissuyaa

2019/06/27 07:29

async/awaitをfor文の中で使うということですか?
Lhankor_Mhy

2019/06/27 07:38

追記拝読。asyncはループの外に置く形でしょうね。 というか、使っていいのですね?
guest

回答2

0

ベストアンサー

awaitを使う方法

js

1(async ()=>{ 2 3for (let i = 1; i <= pdfDocument.numPages; i++) { 4 let page = await pdfDocument.getPage(i); 5 console.log('page #: ' + i); 6 let viewport = page.getViewport({ scale: PAGE_SCALE, }); 7 let textContent = await page.getTextContent(); 8 // building SVG and adding that to the DOM 9 var svg = buildSVG(viewport, textContent); 10 document.getElementById('pageContainer').appendChild(svg); 11} 12 13})()

Promise.all()を使う方法

js

1let arr = []; 2for (let i = 1; i <= pdfDocument.numPages; i++) { 3 arr.push( 4 pdfDocument.getPage(i) 5 .then(function (p) { 6 page = p; 7 console.log('page #: ' + i); 8 viewport = page.getViewport({ scale: PAGE_SCALE, }); 9 return Promise.all([viewport, page.getTextContent()]); 10 }) 11 ); 12} 13Promise.all(arr).then(function(resultArr){ 14 contentArr.forEach(x=>{ 15 var svg = buildSVG(...x); 16 document.getElementById('pageContainer').appendChild(svg); 17 }) 18});

どちらも動作確認してません。

投稿2019/06/27 08:59

編集2019/06/27 09:20
Lhankor_Mhy

総合スコア36074

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

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

Lhankor_Mhy

2019/06/27 09:04 編集

あ、Promise.allの方、配列返す形じゃ動かないか。まるっとPromiseでまとめないとだ。 それはださいなー
jesuissuyaa

2019/06/27 11:24

無事動作しました!ありがとうございます!!
guest

0

コードまで書きませんが

  1. 非同期で1ページずつpdfの読み込みを行っている以上、1→2→3の順に処理を開始しても2→1→3のように完了する順番が違うのは当たり前
  2. 全ページの変換処理を行った結果をソートしたいなら、変換をする箇所ではページ番号と中身のデータが対になったデータを返してやり、全ページの処理の完了を待って変換が終わったデータをソートしてから次の処理(表示)に流す必要がある
  3. 2が嫌なら同期的に処理をするしかない(1ページずつwaitするみたいな)

というわけで、Promiseの使い方を調べて修正してみてはどうでしょう。

投稿2019/06/27 07:43

gentaro

総合スコア8949

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問