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

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

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

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

2回答

712閲覧

Promise.all・非同期処理での通信待機について

takamon

総合スコア7

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

1グッド

1クリップ

投稿2022/10/25 14:13

前提

promiseについて知識不足で、お手数ですが伺えれば幸いです。

実現したいこと

リスト(配列)にあるファイルをfetchしてきて、データがあればデータを配列に格納し、
データがなければnullを格納したいです。
その後、次の処理に進みたいです。

該当ソースコード

現在、取得できているデータ量がバラバラとなっており、promise.allがうまく使えていないと思います。

javascript

1 const getData_A = async () => { 2 await Promise.all( 3 Files.map((req, idx) => { 4 const res = fetch(req); 5 6 const data = res.then((response) => { 7 if (response.ok) { 8 return response.json(); 9 } 10 if (!response.ok) { 11 return null; 12 } 13 }).then((value) => { 14 value !== null ? (Obj[idx + 1] = value) : (Obj[idx + 1] = null); 15 }); 16 }) 17 ); 18 } 19 20const processAll = async function () { 21 // Aと同じようにB、Cも別で取得しようとしてます。 22 Promise.all([getDataA(), getData_B(), getData_C()]).then((res) => { 23           // 別処理へ。 24 }); 25}; 26 27processAll(); 28

なにかおわかりになりましたら、ご指導いただければ幸いです。

退会済みユーザーを押しています

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

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

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

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

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

yambejp

2022/10/26 08:36

データがあればとかなければ・・・をきちんと定義したほうがよいでしょう。 受け取るデータはjsonであれば文法違反でなければ必ずデータはあると思いますが・・・
takamon

2022/10/26 13:47

ご指摘の内容はごもっともです。 fetchしてきたデータの流れや、データの有無など、状況と状態を把握してコードを書けるようにしたいと思います。 今回は、あるタイミングで新規JSONが追加配信されるというもので、ファイル名はわかっているので、配列でファイル名を記載しておき、ループでajaxしたいというものです。 データがないというあやふやな書き方で、申し訳ありません。 ファイルがない場合もあるということを想定して書きたいなと思ってる次第です。 ご指摘ありがとうございました。
guest

回答2

0

ベストアンサー

押さえておくことは以下の4点です。

  1. Promise.all() には引数としてPromiseオブジェクトの配列を渡す必要がある。
  2. 配列のmapメソッドでPromiseの配列を作るのであれば、mapメソッドの引数に渡すコールバック関数は Promiseを返していなければならない。
  3. 関数 fetch() はPromiseを返す
  4. Promiseのインスタンスメソッドの then (や catch )メソッドもまたPromiseを返す

上記を確認するためのサンプルを下記のcodepenに作りました。

👉 https://codepen.io/su507/pen/ZEREjdX?editors=0010

手元にコピペするなりして各処にconsole.logを入れたり、コードを短く書いているところを補ったりして修正しながら動かしてみてください。(codepen にユーザー登録するとforkして自分のコードとしてブラウザ上で修正できます。)

この例では

  • データのfetch元に jsonplaceholder というサービスを使っています。
  • Files オブジェクトは A, B, C というキーを持つオブジェクトです。
  • Filesの各キーの値はjsonplaceholderからデータを取得するURLの配列です。A はユーザー、BはTODOアイテム、C は何らかの投稿の各1アイテムを取得するURLの配列になっています。
  • AB のURL配列の3つめの要素はデータが取得できないURLにわざとしています。これらのURLのA のほうはユーザーIDが9999のユーザー情報を取得しようとして 404 NOT FOUND が返されるURLです。B のほうはURL先頭のhttpshoge に変えて fetch 自体がエラーになるようなURLにしています。
  • processAll関数は、File オブジェクトが持つ 各URLに対してfetchを実行してその結果をテーブルに表示します。

このサンプルについての不明点はコメントいただければ返信します。

補足

何となく分かった気になったという理解の仕方では白紙の状態からやりたいことを実現するコードを独力で書ききるところまで行くのは難しいです。
JavaScript Promiseの本 などを読み、様々な概念や仕組み、メソッドについての理解を試すサンプルコードを作成してみるのがよいでしょう。

投稿2022/10/25 21:21

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

takamon

2022/10/26 13:39

ポイントなど、細かく記載いただき、またサンプルまで本当にありがとうございます。 なんとなくわかった程度ではいけないとは思いつつ、苦手意識から、避けてしまっていたように思います。 帰宅後にすぐ試してみたいと思います。 参考書籍まで本当にありがとうございます。
takamon

2022/11/03 17:18

とても丁寧にご回答いただきありがとうございます。 内容を確認してコードを修正して見ました。 サンプルや参考までいただき、感謝です。 以下、変更後になります。 ---------------------------------------------------- const getData_A = async () => { let results = []; Files.forEach((req) => { results.push(getfetchData(req)); }); return Promise.all(results); }; async function getfetchData(req) { const promise = fetch(req); return promise .then((response) => { if (response.ok) return response.json(); if (!response.ok) return null; }) } const processAll = async function () { await Promise.all([getData_A(), getData_B(), getData_C()]).then((res) => { // 以降の処理 }); }; $(async function () { await processAll(); }); としてみました。 ありがとうございました。
退会済みユーザー

退会済みユーザー

2022/11/03 19:34

解決されたようですね、よかったです👏
guest

0

Promise.allに対しては、Promiseの配列を渡さないと意味がありません。

mapの中でthenをセットしているので、このthenPromise.allと無関係に、それぞれの通信が終わったタイミングで実行されてしまいます。

投稿2022/10/25 14:21

maisumakun

総合スコア145184

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

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

takamon

2022/10/25 16:33 編集

そうそうにご回答ありがとうございます。 こちら、問題箇所をご指摘いただいて本当にありがとうございます。 ですが、少し不安でもあります。 自分は、promiseを配列に格納するという認識が全くありませんでした。 本当にありがとうございます。 厚かましいかとは思いますが、もしもコードにおかしい点がございましたらご指摘いただけるとうれしいです。 ```javascript const getData_A = async () => { const results = []; File.forEach((req, idx) => { const res = fetch(req); results.push(res); }); results.forEach((each, idx) => { each .then((response) => { if (response.ok) return response.json(); if (!response.ok) return null; }) .then((value) => { value !== null ? (Obj[idx + 1] = value) : (Obj[idx + 1] = null); }); }); return Promise.all([Obj]); }; ``` 迅速にご回答いただきありがとうございます。
maisumakun

2022/10/25 22:53

> もしもコードにおかしい点がございましたらご指摘いただけるとうれしいです。 「各個のPromiseそれぞれにthenをセットして、バラバラなタイミングで実行される」という点が、全く改善していません。 全部の結果を一斉に得たいなら、Promise.allの結果に対して.thenで繋ぐ必要があります。
takamon

2022/10/26 13:35

度々の回答ありがとうございます。 Promise.allの結果に対してthenで繋ぐ。とのこと少し他の方のご回答も併せて参考にさせてもらい、考えます。 本当にありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問