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

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

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

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

3回答

2057閲覧

入れ子になっている関数で、非同期処理を実現したい。

hiroHero

総合スコア6

JavaScript

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

2クリップ

投稿2021/05/10 08:03

前提・実現したいこと

入れ子になっている関数の最深部に非同期で処理したい関数がある時、それらが全て完了した時に行いたい処理を関数の外側で処理する方法が知りたい。

該当のソースコード

javascript

1var array = [['リンゴ', 'バナナ'], 2 ['イチゴ','メロン'] 3]; 4 5array.forEach((item) => { 6 item.forEach((item) => { 7 setTimeout(() => { 8 console.log(item); 9 },1000); 10 }); 11}); 12 13console.log('finish');

finishを最後に表示させたい。
もしできたら、

試したこと

ここに問題に対して試したことを記載してください。

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

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

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

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

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

guest

回答3

0

ベストアンサー

Promise.all()を利用するとよいでしょう。
Promise.all() - JavaScript | MDN

javascript

1var array = [ 2 ['リンゴ', 'バナナ'], 3 ['イチゴ','メロン'] 4]; 5 6var promiseList = []; 7 8array.forEach((item) => { 9 item.forEach((item) => { 10 11 var promise = new Promise((resolve, reject) => { 12 setTimeout(() => { 13 console.log(item); 14 resolve(); 15 },1000); 16 }); 17 18 promiseList.push(promise); 19 20 }); 21}); 22 23Promise.all(promiseList).then(() => { 24 console.log('finish'); 25});

投稿2021/05/10 08:32

ku__ra__ge

総合スコア4524

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

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

0

forEachの様な構文処理ではなくmapのような戻り値を得た方がpromiseが活かしやすいですね

javascript

1Promise.all(array.map((item) => new Promise(async resolve=>{ 2 await Promise.all(item.map((item) => new Promise(resolve=>{ 3 setTimeout(() => { 4 console.log(item); 5 resolve(); 6 },1000); 7 }))); 8 resolve(); 9}))).then(()=>{ 10 console.log('finish'); 11});

もしくは二次配列ならflatしてしまう方が楽です
またPromise.allするならsetTimeout内でconsoleせず戻りを待ってから出力するほうが楽です

javascript

1Promise.all(array.flat().map((item) => new Promise(resolve=>{ 2 setTimeout(() => { 3 resolve(item); 4 },1000); 5}))).then((data)=>{ 6 data.forEach(item=>console.log(item)); 7 console.log('finish'); 8});

投稿2021/05/11 00:48

yambejp

総合スコア116835

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

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

0

入れ子になっている関数の最深部に非同期で処理したい関数がある

setTimeoutシングルスレッドなので、全ての setTimeout を実行後に console.log('finish') をしかけた setTimeout (待ち時間0)をしかければ、最後に動作します。

JavaScript

1item.forEach((item) => { 2 setTimeout(() => { 3 console.log(item); 4 },1000); 5});

1秒後にタイマー処理が連続実行されるので、

  1. setTimeout を一つにする
  2. forEachconsole.log(item)
  3. console.log('finish')

にすれば、格段にシンプルなコードで書けます。

Re: hiroHero さん

投稿2021/05/10 08:57

think49

総合スコア18189

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

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

think49

2021/05/11 01:05

続いたのでコメントで補足します、 主題は2つ目のほうで「1秒後に4個のタイマー処理を連続して実行する」のは明らかな無駄なので、「1秒後に一つのタイマー処理(forEach含む)を実行する」に修正したほうが効率も見通しも良くなると考えます。 一つにまとまったら、console.log('finish'); はタイマー処理の中で書くのと大して変わりません。 どうしても console.log('finish'); を他スコープに逃がしたければ、setTimeoutの第三引数に関数を指定してコールバックすれば良いかと。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問