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

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

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

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

非同期処理

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

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

4回答

4189閲覧

Javascript:Promiseをresolveしたけれどもthenが実行されない

benkyo.fun

総合スコア9

JavaScript

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

非同期処理

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

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

3クリップ

投稿2019/08/15 22:06

実現したいことと問題

「オブジェクトに格納されているプロパティに対して、順番に時間のかかる処理を行いたい、そして処理が全部終わってから、更に別の処理を実行したい。」という状況です。これを実現するために、Promiseを使って、再帰処理風にコードを書いてみました。

・ですが、順番に実行されたのは良いのですが、shifter().thenの中のconsole.logが実行されないようで、"thenの中"が表示されません。自分ではlateFuncの中のpromiseと同じように記述しているつもりですので、そちらはresolve後のthenが実行されて、こちらが実行されないという理由が分かりませんでした。

・'shifter()の中のresolveの後'と'lateFunc()の中のresolveの後'が表示されます。自分の理解ではresolveすると、処理がpromiseのthenに移ると思っていたんですが、何か誤解しているのでしょうか。

ソースコード

JavaScript

1var hoge = { 2 1:"manzana", 3 2:"platano", 4 3:"naranja", 5 4:"ciluera", 6 5:"fresa", 7 6:"melocoton", 8 7:"sandia", 9 8:"uva", 10}; 11 12var props =Object.keys(hoge); 13 14var value:string|undefined; 15 16shifter().then(()=>{ 17 console.log('thenの中'); 18}); 19 20console.log('shifter()の次') 21 22function shifter(){ 23 return new Promise((resolve, rejected)=>{ 24 console.log('shifter()の中のPromiseの後'); 25 if ((value = props.shift()) !== undefined){ 26 lateFunc(value).then(()=>{ 27 shifter(); 28 }); 29 }else{ 30 console.log('shifter()の中のelse'); 31 resolve(); 32 console.log('shifter()の中のresolveの後'); 33 } 34 }) 35} 36 37function lateFunc(arg:string){ 38 return new Promise((resolve, rejected)=>{ 39 setTimeout(()=> { 40 console.log('lateFunc:'+arg); 41 resolve(); 42 console.log('lateFunc()の中のresolveの後'); 43 }, 100); 44 }) 45} 46

処理結果

shifter()の中のPromiseの後 add.page.ts:82 shifter()の次 add.page.ts:102 lateFunc:1 add.page.ts:104 lateFunc()の中のresolveの後 add.page.ts:86 shifter()の中のPromiseの後 add.page.ts:102 lateFunc:2 add.page.ts:104 lateFunc()の中のresolveの後 add.page.ts:86 shifter()の中のPromiseの後 add.page.ts:102 lateFunc:3 add.page.ts:104 lateFunc()の中のresolveの後 add.page.ts:86 shifter()の中のPromiseの後 add.page.ts:102 lateFunc:4 add.page.ts:104 lateFunc()の中のresolveの後 add.page.ts:86 shifter()の中のPromiseの後 add.page.ts:102 lateFunc:5 add.page.ts:104 lateFunc()の中のresolveの後 add.page.ts:86 shifter()の中のPromiseの後 add.page.ts:102 lateFunc:6 add.page.ts:104 lateFunc()の中のresolveの後 add.page.ts:86 shifter()の中のPromiseの後 add.page.ts:102 lateFunc:7 add.page.ts:104 lateFunc()の中のresolveの後 add.page.ts:86 shifter()の中のPromiseの後 add.page.ts:102 lateFunc:8 add.page.ts:104 lateFunc()の中のresolveの後 add.page.ts:86 shifter()の中のPromiseの後 add.page.ts:92 shifter()の中のelse add.page.ts:94 shifter()の中のresolveの後

実行環境

試した環境は以下の3つで、いずれも同じ結果です。
node v10.16.0
ionic 5.2.4
TypeScript.orgのplayGround http://www.typescriptlang.org/play/index.html

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

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

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

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

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

gentaro

2019/08/15 23:00 編集

> shifter().thenの中のconsole.logが実行されないようで これshifter()っていきなり実行して戻り値に対してthen()を呼び出してますが、この関数自体はどこで定義されてるんでしょう? あとlateFunc(arg:string)って数値しか渡ってこないように見えますがstringであってるんでしょうか?
benkyo.fun

2019/08/15 23:01

コメントありがとうございます。 ・この関数自体(おそらくPromiseなんだろうけど)をどこで定義されてるんでしょう? →呼出のすぐ下の所です。(function shifter(){のところ) ・あとlateFunc(arg:string)って数値しか渡ってこないように見えますがstringであってるんでしょうか? →Object.keysの戻り値がstring|undefinedです。
gentaro

2019/08/15 23:14

あ、なるほど。ちゃんと読めてなかった。 なんかややこしいな…。
benkyo.fun

2019/08/15 23:15

すみません。入力が不定長のオブジェクトという前提だと、こんな風にしか書けませんでした。
guest

回答4

0

ベストアンサー

こういうことでは。

diff

1var hoge = { 2 1:"manzana", 3 2:"platano", 4 3:"naranja", 5 4:"ciluera", 6 5:"fresa", 7 6:"melocoton", 8 7:"sandia", 9 8:"uva", 10}; 11 12var props =Object.keys(hoge); 13 14var value:string|undefined; 15 16shifter().then(()=>{ 17 console.log('thenの中'); 18}); 19 20console.log('shifter()の次') 21 22function shifter(){ 23 return new Promise((resolve, rejected)=>{ 24 console.log('shifter()の中のPromiseの後'); 25 if ((value = props.shift()) !== undefined){ 26 lateFunc(value).then(()=>{ 27- shifter(); 28+ resolve(shifter()); 29 }); 30 }else{ 31 console.log('shifter()の中のelse'); 32 resolve(); 33 console.log('shifter()の中のresolveの後'); 34 } 35 }) 36} 37 38function lateFunc(arg:string){ 39 return new Promise((resolve, rejected)=>{ 40 setTimeout(()=> { 41 console.log('lateFunc:'+arg); 42 resolve(); 43 console.log('lateFunc()の中のresolveの後'); 44 }, 100); 45 }) 46}

追記

JavaScript

1shifter().then(()=>{ 2 console.log('thenの中'); 3});

の部分を

JavaScript

1var a = shifter(); 2console.log(a)

なりにして、Promiseの状態を見ればpendingになってるんでthenが実行されない原因に気付けると思います。

投稿2019/08/15 23:43

編集2019/08/15 23:49
gentaro

総合スコア8949

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

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

benkyo.fun

2019/08/16 00:00

なるほど。解決できました。 スマートな書き方と疑問解決への道筋を示していただいたので、BAとさせてください。
guest

0

console.log('thenの中')が呼ばれないのは再帰処理の最初のresolveを呼んでないからです。
もっといい方法があるかもしれませんが再帰処理の最初のresolveをresolve2に保管するよう修正してみました。

var hoge = { 1:"manzana", 2:"platano", 3:"naranja", 4:"ciluera", 5:"fresa", 6:"melocoton", 7:"sandia", 8:"uva", }; var props =Object.keys(hoge); var value:string|undefined; var resolve2:any; shifter().then(()=>{ console.log('thenの中'); }); console.log('shifter()の次') function shifter(){ return new Promise((resolve, rejected)=>{ if(!resolve2)resolve2=resolve; console.log('shifter()の中のPromiseの後'); if ((value = props.shift()) !== undefined){ lateFunc(value).then(()=>{ shifter(); }); }else{ console.log('shifter()の中のelse'); resolve2(); console.log('shifter()の中のresolveの後'); } }) } function lateFunc(arg:string){ return new Promise((resolve, rejected)=>{ setTimeout(()=> { console.log('lateFunc:'+arg); resolve(); console.log('lateFunc()の中のresolveの後'); }, 100); }) }

投稿2019/08/15 23:37

querykuma

総合スコア777

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

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

benkyo.fun

2019/08/15 23:59

ありがとうございます。その点に気づけていませんでした。resolveが呼ばれない処理を作ってしまっていました。
退会済みユーザー

退会済みユーザー

2019/08/16 00:40

うーん、わざわざresolve2にする必要あるのかな…
guest

0

みなさんありがとうございました。

「自分の理解ではresolveすると、処理がpromiseのthenに移ると思っていたんですが、何か誤解しているのでしょうか。」
の件は、検索して回答が見つかりました。探し方が甘かったです。

投稿2019/08/16 00:37

benkyo.fun

総合スコア9

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

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

0

単に以下の式が常にtrueになりつづけるので再帰処理を抜けられないだけじゃ無いかと思います。

(value = props.shift()) !== undefined

投稿2019/08/15 23:41

KuwabataK

総合スコア306

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

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

gentaro

2019/08/15 23:52

> add.page.ts:92 shifter()の中のelse が表示されてるんでそれはないですな。
KuwabataK

2019/08/15 23:58

あー処理結果最後まで見てませんでした。 確かに最後でループ抜けてましたね。 単純に上位の階層のpromiseがresolveされてないだけですね。
benkyo.fun

2019/08/16 00:01

コメントありがとうございます。ややこしいコードで誤解させてしまいすみませんでした。
KuwabataK

2019/08/16 00:21

いえ、私がちゃんと読まなかったのが悪いので、謝る必要はないです。 こちらこそ早とちりしてしまってすいませんでした
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問