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

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

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

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

Q&A

解決済

2回答

273閲覧

Javascript Promise .then の実行タイミングについて

krnkn6

総合スコア6

JavaScript

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

0グッド

1クリップ

投稿2024/11/15 03:42

実現したいこと

「コールバック地獄」 と 「コールバック地獄をPromiseで置き換えた処理」2つのコードを同時に実行した際の実行タイミングについての質問です。

実現したいコード自体は調べたサイトに載ってあります。

今回は、「自分が試したコードの結果」が「調べサイトに掲載してあるコードの結果」と同じにならない仕組み的なことについてお聞きしたいです。

発生している問題・分からないこと

まず、「コールバック地獄のコード」 と 「Promiseのコード(調べたサイト)」 を同時に実行します。
すると、コンソールには

「 1秒 1 2秒 2 3秒 3 」

と、想定している結果が表示されます。(コールバック地獄 ⇒ .then の順に実行)

次に、「コールバック地獄のコード」と「Promiseのコード(私が試したコード)」を同時に実行すると、

「 1秒 1 2 2秒 3 3秒」

と、表示されます。(2秒から .then が先に実行)

.then は Promise が fulfilledの状態(処理が完了)したタイミングで実行されるという認識です。

上記の認識で自分のコードを見た際、1つ目の .then が開始された時点で fulfilled になり2つ目の .then が実行開始。
そのあと、2つ目のsetTimeout が実行開始されているように見えます。

なぜ、自分のコードでは 2つ目以降の .then が setTimeout よりも先に処理されているのでしょうか。

該当のソースコード

js

1//コールバック地獄のコード 2 3setTimeout(function () { 4 console.log('1秒'); 5 6 setTimeout(function () { 7 console.log('2秒'); 8 9 setTimeout(function () { 10 console.log('3秒'); 11 }, 1000); 12 13 }, 1000); 14}, 1000);

js

1// 調べたサイトのコード 2let delay = (ms) => { 3 return new Promise((resolve) => { 4 setTimeout(resolve , ms); 5 }); 6} 7 8delay(1000) 9 .then(() => { 10 console.log(1); 11 return delay(1000); 12 }) 13 .then(() => { 14 console.log(2); 15 return delay(1000); 16 }) 17 .then(() => { 18 console.log(3); 19 });

js

1// 私が試したコード 2 3let promise = new Promise((resolve) => { 4 resolve(); 5}) 6.then(() => { 7 setTimeout(() => { 8 console.log(1); 9 } , 1000); 10}) 11.then(() => { 12 setTimeout(() => { 13 console.log(2); 14 } , 2000); 15}) 16.then(() => { 17 setTimeout(() => { 18 console.log(3); 19 } , 3000); 20});

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

説明しづらかったので、上記にコードはまとめております。

補足

特になし

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

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

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

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

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

guest

回答2

0

ベストアンサー

> なぜ、自分のコードでは 2つ目以降の .then が setTimeout よりも先に処理されているのでしょうか。

まず、 then メソッド の仕様を把握しましょう。

Promiseによる解決 - とほほのPromise入門 - とほほのWWW入門

つまり、戻り値が Promise である必要があります。

先ほどのコードを見てみましょう。

js

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

何も返していませんね。 つまり undefined を返しています。

つまりこれと同じです。

js

1.then(() => { 2 setTimeout(() => { 3 console.log(1); 4 } , 1000); 5 return Promise.resolve(undefined); 6})

その為、setTimeout の完了を待つことはないです。

setTimeout の時間を待ちたい場合は次の様に Promise のコールバックの第一引数 resolve を呼んでやることで完了を伝えることができます。

js

1.then(() => { 2 return new Promise( 3 resolve => 4 setTimeout(() => { 5 console.log(1); 6 resolve(); 7 } , 1000) 8 ); 9})

以上。

投稿2024/11/15 04:30

編集2024/11/15 04:50
juner

総合スコア453

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

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

krnkn6

2024/11/15 13:09 編集

大変申し訳無いのですが、ご教示いただいたにもかかわらずよく分かりませんでした。 そのため、改めてドキュメントを読み直し .then のおおまかな仕様を自分なりに理解してきました。 まず、.then() の仕様について大まかにまとめると下記になるかと思います。 ●Promiseオブジェクトのメソッド ●Promiseが待機 から 履行などに 決定されると .then()内の処理が実行  (後続の同期タスクが完了後実行) ●引数に履行ハンドラー、拒否ハンドラー指定可能 ●値の引き渡し可能 (まだまだ私の理解不足なところもあり、他にも仕様があるかと思いますが。。。) そのうえで、「戻り値が Promise の必要がある」というのが分かりませんでした。 .then は Promiseオブジェクトが 待機状態から履行状態などに決定した際に実行するただのハンドラーではないのでしょうか。 戻り値が Promise の必要があるというのは、Promiseオブジェクトを生成する際の話ではなく、.then()内の話になるのでしょうか。 (とほほ様ページ内「aFunc2(data)」でも Promiseが返り値に指定されており、「sample_promise()内の.then()」は、ただ aFunc2(100)から受け取った値をコンソールに表示しているだけに見えるのですが。) 的外れな質問をしていたら大変申し訳ございません。
maisumakun

2024/11/15 23:33 編集

> .then は Promiseオブジェクトが 待機状態から履行状態などに決定した際に実行するただのハンドラーではないのでしょうか。 もちろん、ただのハンドラとして使うこともできます。ただし、.then(その1とします)のハンドラーが「Promiseを返すならば」、その1の後につなげる.then(その2)は「その1のハンドラーが返したPromiseの完結を待つ」というようになっています。 thenその1でPromiseを返さなければ、thenその2はすぐに実行されます。
maisumakun

2024/11/15 23:57

あと、setTimeoutは引数の関数を遅延実行させるだけで周囲の実行順には影響しないこと、具体的には setTimeout(() => console.log('100ミリ秒後に表示'), 100); console.log('こちらが先に表示される'); ことは大丈夫でしょうか。
krnkn6

2024/11/16 02:14

> 「Promiseを返すならば、その1のハンドラーが返したPromiseの完結を待つ」 そのような仕様があったのですね! 理解できました。 ありがとうございます! setTimeoutの実行順に関しては大丈夫です。
guest

0

単純にコールバックから別の処理をネストすると、遅延分どんどん処理がおくれていき、普通に並列で動かしているものに抜かれるという図式では?

javascript

1const pass=(txt=null,start=0)=>{ 2 const pass=performance.now()-start; 3 if(txt) console.log(`${txt}:${pass}`); 4 return pass; 5} 6const start=pass(); 7setTimeout(()=>{ 8 pass('a1',start); 9 setTimeout(()=>{ 10 pass('a2',start); 11 start;setTimeout(()=>{ 12 pass('a3',start); 13 },1000); 14 },1000); 15},1000); 16setTimeout(()=>pass('b1',start),1000); 17setTimeout(()=>pass('b2',start),2000); 18setTimeout(()=>pass('b3',start),3000);

投稿2024/11/15 05:55

yambejp

総合スコア116468

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

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

krnkn6

2024/11/16 02:22

2つ目以降の.thenが即時に実行されることから、並列処理の分ネスト処理よりも先に実行されていたということですね。 理解できました! ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問