🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JavaScript

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

非同期処理

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

Q&A

解決済

3回答

3701閲覧

JavaScript Promise.then()の中で非同期処理を行なった場合に、次のthenはその処理完了を待ってくれないのはPromiseの仕様上仕方ないのか?

NayuNayu

総合スコア11

JavaScript

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

非同期処理

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

0グッド

3クリップ

投稿2021/03/11 06:21

編集2021/03/11 14:22

質問事項

JavaScript初学者です。
Promise.then().then()... を使えば非同期処理を逐次的にコントロールできることがわかりました。
また、Promise.then()は、Promiseがresolveやrejectされるまで実行されないことは理解しています。

ただ、その次のthen、はその前のthenの非同期処理結果を待ってくれないのでしょうか。
(その場合はthenの非同期処理の中でPromiseインスタンス生成して、別のthenチェーンを繋げるしかない?)

例えばのソースコード

JavaScript

1 new Promise(function (resolve) { 2 console.log("new promise start"); 3 setTimeout(function () { 4 console.log("new promise setTimeout"); 5 resolve();        <= このresolveされるまで次のThenは動かない(非同期を待つ) 6 }, 0); 7 console.log("new promise end"); 8 }) 9 .then(function () {    <= setTimeoutでresolveされたらこのThenが動く 10 console.log("then1"); 11 return "then1 param"; 12 }) 13 .then(function (v) {    <= 前のThenがresolve("then1 param")されたからこのThenが動く 14 console.log(v); 15 console.log("then2 start"); 16 setTimeout(function () { 17 console.log("then2 setTimeout"); 18 return new Promise(function (resolve) { 19 console.log("then2 new promise start"); 20 resolve("then2 new promise");      <= setTimeoutの中でresolveしたけど。。。 21 }); 22 }, 0); 23 console.log("then2 end"); 24 //then同期処理内でreturnされない場合はresolve()が返される 25 }) 26 .then(function (v) { 27 console.log(v);     <= 前のThenのsetTimeoutを待たずresolve()で動いてしまう 28 console.log("then3"); 29 }); 30 31 console.log("end"); 32

new promise start
new promise end
end
new promise setTimeout
then1
then1 param
then2 start
then2 end
undefined     <= 前のThenのsetTimeoutを待たないのでresolve()で動いてしまう
then3
then2 setTimeout    <= 前のThenのsetTimeout結果は当然最後になる
then2 new promise start

こうするしかない?

質問事項にある通り、thenの非同期処理の中でPromiseインスタンス生成して、別のthenチェーンを繋げるしかないのでしょうか?

JavaScript

1 new Promise(function (resolve) { 2 console.log("new promise start"); 3 setTimeout(function () { 4 console.log("new promise setTimeout"); 5 resolve();        <= このresolveされるまで次のThenは動かない(非同期を待つ) 6 }, 0); 7 console.log("new promise end"); 8 }) 9 .then(function () {    <= setTimeoutでresolveされたらこのThenが動く 10 console.log("then1"); 11 return "then1 param"; 12 }) 13 .then(function (v) {    <= 前のThenがresolve("then1 param")されたからこのThenが動く 14 console.log(v); 15 console.log("then2 start"); 16 setTimeout(function () { 17 console.log("then2 setTimeout"); 18 return new Promise(function (resolve) { 19 console.log("then2 new promise start"); 20 resolve("then2 new promise");      <= setTimeoutの中でnew Promise 21 }).then(function (v) { 22 console.log(v);     <= setTimeoutの中のPromiseのresolveを待ってくれる 23 console.log("then3"); 24 }); 25 }, 0); 26 console.log("then2 end"); 27 }) 28 29 30 console.log("end"); 31

new promise start
new promise end
end
new promise setTimeout
then1
then1 param
then2 start
then2 end
then2 setTimeout
then2 new promise start
then2 new promise
then3

回答ありがとうございました!!

根本的なthen()処理の理解が足りていない質問でした。。。
全員BAしたいくらいですが無理なので、コードまで書いてくださった@SAKASHITA-Kokiさんにさせていただきます。

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

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

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

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

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

guest

回答3

0

setTimeoutのコールバックがpromiseをリターンしてもそれは単に
コールバックへのreturnでしかないので、thenに影響する戻り値がないでしょう?
PromiseはsetTimeoutを囲むようにつかってください

投稿2021/03/11 06:39

編集2021/03/11 06:40
yambejp

総合スコア116661

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

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

NayuNayu

2021/03/11 14:01

確かにそうですね。ハッと気づきました。(しょうもない質問でした。。。) > PromiseはsetTimeoutを囲むようにつかってください こうすることでPending状態のPromiseを返すことで、解決後に後続のThen()が動くようになると。。。
guest

0

ベストアンサー

js

1new Promise(function (resolve) { 2 console.log("new promise start"); 3 setTimeout(function () { 4 console.log("new promise setTimeout"); 5 resolve(); 6 }, 0); 7 console.log("new promise end"); 8}) 9 .then(function () { 10 console.log("then1"); 11 return "then1 param"; 12}) 13 .then(function (v) { 14 console.log(v); 15 console.log("then2 start"); 16 return new Promise(function (resolve) { 17 console.log("then2 new promise start"); 18 setTimeout(function () { 19 console.log("then2 setTimeout"); 20 resolve("then2 new promise"); 21 }, 0); 22 }); 23}) 24.then(function (v) { 25 console.log(v); 26 console.log("then3"); 27}); 28 29console.log("end");
new promise start new promise end end new promise setTimeout then1 then1 param then2 start then2 new promise start then2 setTimeout then2 new promise then3

thenは必ずPromiseを返します! thenに渡した関数内で文字列や数値などを返しても、then自体はその値でresolveされたPromiseを返します。
チェーンされたthenはresolveされた(fulfilled)Promiseを受け取るのでスグに実行されます。

載せられたコードの問題点はthen2のsetTimeoutに渡した関数内でPromiseを返している点です。ここでPromiseを返しても意味がないことが分かるでしょうか...? そのreturnはsetTimeoutに渡した無名関数のreturnであって、thenに渡した無名関数のreturnではないのです。
なのでthen2はreturnなしで終了(つまりundefinedをreturn)し、then3にはundefinedが渡されます。

こうするしかない?コードは折角のPromiseの利点(所謂コールバック地獄)を台無しにしてしまうので、美しくないですね...
then2内でPromiseを作って返してやり、そのPromiseの中で非同期処理をするのが素直な実装かな、と思います。

どうでしょうか...!?

投稿2021/03/11 07:05

編集2021/03/11 07:07
SAKASHITA-Koki

総合スコア27

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

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

NayuNayu

2021/03/11 14:18

> then2はreturnなしで終了(つまりundefinedをreturn)し、then3にはundefinedが渡されます。 やっぱりそうですよね。ただ、解決法がわかりませんでした。。。 > then2内でPromiseを作って返してやり、そのPromiseの中で非同期処理をするのが素直な実装かな、と思います。 ですね!Pending状態のPromiseを返して、解決(Resolve or Reject)を非同期にすれば後続のThenも制御できそうです!ありがとうございます。
guest

0

Promise を返せばよさそうな?

他の pending 状態の Promise オブジェクトを返した場合、 then によって返された Promise の解決/拒絶は、ハンドラーによって返された Promise の解決/拒絶結果に依存します。また、 then によって返された Promise の解決値は、ハンドラーによって返された Promise の解決値と同じになります。

Promise.prototype.then() - JavaScript | MDN

投稿2021/03/11 06:41

Lhankor_Mhy

総合スコア36928

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

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

NayuNayu

2021/03/11 14:08

MDNみるとまさにその通りのことが書いてましたね(調査不足でしたスミマセン) return new Promise... の中でsetTimeoutすることでそのThenでは一旦Pending状態のPromiseを返す=>後続のThenは動けない=>setTimeoutで解決する=>後続のThenが動く ような感じですね。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問