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

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

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

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

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

Q&A

解決済

3回答

1230閲覧

async awaitについての初歩的な質問

Avent

総合スコア47

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

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

0グッド

0クリップ

投稿2021/09/19 06:40

awaitとasyncの使い方についての質問です。
「awaitを使うと値がreturnされるまで処理が一時停止される」という理解で以下のコードを記述しましたが、正しく動きません。

js

1dothis(); 2 3async function dothis(){ 4 console.log('1') 5 console.log(await say2()) 6 console.log('3') 7} 8 9async function say2() { 10 setTimeout(() => { 11 return 2; 12 }, 1000) 13}

こちらを実行すると

js

11 2undefined 33 // この後1秒待ってからプログラムが終了する。

となってしまいます。
実現したい結果は以下です。

js

11 // ここで1秒止まって 22 33

どうすればよいのでしょうか?

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

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

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

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

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

guest

回答3

0

そやねえ。見たとこ3点ありよる。

(1) say2()

javascript

1 function say2() { 2 return new Promise(resolve => { 3 setTimeout(() => { 4 resolve(2) 5 }, 1000) 6 }) 7 }

に修正

(2) dothis の呼び出しにも await を付ける。

javascript

1await dothis();

(3) そして最後に、これらを含む関数も async にしとく。

サンプル

投稿2021/09/19 07:16

編集2021/09/22 17:11
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

ベストアンサー

1 . setTimeout内のreturnについて

js

1async function say2() { 2 setTimeout(() => { 3 return 2; 4 }, 1000) 5}

この中の、() => {return 2;}は、say2とは別の関数であるため、returnで返る場所はawait say2()ではありません。(setTimeoutが戻り値を操作しないので、実質どこにも返していないです)

2 . say2の終了時点について
say2の中でsetTimeoutを使った第一引数に書かれている関数は、async/awaitを使っていない呼び出しと同じです。つまり内部の関数の終了を待ちません。
そのため、say2でawaitに該当する箇所がなく、即時に関数が終了します。
(何が言いたいかというと、仮にreturn 2が正しく返せても、出力は1,3,2になります)

1,2から、戻り値を正しい順に、適切に返す記述が必要になります。
今回はPromiseを使いますが、説明が長くなるので詳しくは一度調べてみてください。

js

1async function say2() { 2 const ret = await new Promise((resolve) =>{ 3 setTimeout(() => { 4 resolve(2); 5 }, 1000)} 6 ); 7 return ret; // 変数に一度置いていますが、直でreturnしてもいいです 8}

本来取得したい2をresolveで受け、またawaitで待機してから返すことで、期待した動きになっているのではないでしょうか。

投稿2021/09/19 07:25

yuuyu

総合スコア1139

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

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

Avent

2021/09/19 07:45 編集

回答ありがとうございます! 期待した通りの動作を行うことができました。 setTimeoutの中の関数でreturnした場合、これをどこかで受け取ることはできるのでしょうか?
yuuyu

2021/09/19 07:48

Promiseを使用した場合、第一引数に渡す関数の引数である(resolve, reject)を経由することで、上記のretの箇所で受け取ることができます。 Promiseを使用しない場合は外部の変数を利用して受け取るか、コールバック関数を自作すれば受け取れます。
Avent

2021/09/19 08:01

なるほど、もう少し調べてみます。 とにかく、回答していただいた方法で期待した通りの実装を行うことはできました!ありがとうございました!
yuuyu

2021/09/19 08:06

余談にはなりますが、単にn秒後に実行して戻り値を受け取りたい場合、以下のサイトのようなsleep関数を作成し、それをawaitで待つコードにすると、何個も関数を呼ぶこともなくシンプルにタイムラグを作成することもできます。 https://hirooooo-lab.com/development/javascript-sleep/
退会済みユーザー

退会済みユーザー

2021/09/27 14:27

BA決定後に失礼します。 この回答にあるコードの say2() に出てくる async と await は無くても同じ効果が得られます。 すなわち回答にあるコードの say2() からasync と awaitを取ったものを say2x() とすると、say2x() は以下のようになります。 function say2x() { const ret = new Promise((resolve) =>{ setTimeout(() => { resolve(2); }, 1000)} ); return ret; } このsay2x()も期待された動作をするPromiseを返します。 回答に書かれているコードの say2() が返すのは、値2で即時resolveするPromiseですが、say2()のコードから async と awaitを無くして得られる上記のsay2x() のほうは、1秒後に値2でresolveするPromise を返します。 回答にあるsay2() のほうは、1秒後に2を返すPromiseがresolveされるまで待って、ret に値2を得てから、return ret; とすることで、2で即時解決されるPromiseを返すことになるので、冗長のように思えます。 あらためてご確認されたほうがよいと思われる点としては、関数dothis()の中で、 console.log(await say2()) という行がありますが、この中の await say2() は、say2() が返すPromiseが解決または拒否されるのを待つわけですが、await される関数(本質問の場合はsay2() )の定義のほうでは、必ず async を先頭につけた async function say2() { … } というものにしなければならないというわけではない、という点です。お役に立てましたら幸いです。
yuuyu

2021/09/27 14:36

簡潔に言えば、 console.log(await say2()) async function say2() の両方でawaitしているため、後者のasync/awaitが冗長になっている、ということですね。 回答する際、dothisの方を注視していなかったために見落としていました。ご指摘ありがとうございます。
guest

0

returnされてるのがsetTimeoutだからだと思います。

例えば下記のようにすると

js

1async function say2() { 2 console.log("call"); 3 setTimeout(() => { 4 return 2; 5 }, 1000) 6} 7/** 81 9call 10undefined 113 12**/

ちゃんと通ってるのが分かります。
returnはあくまでsetTimeoutをreturnしただけで、say2()がreturnされたわけではないのでundefined(返却値がないという意味)となっています。

say2()の中でsetTimeoutを呼び出すのではなく、「1秒後に2をreturnするsay2()を呼び出す」ようにすれば良いのではないでしょうか?

投稿2021/09/19 07:11

編集2021/09/19 07:12
m.ts10806

総合スコア80875

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

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

m.ts10806

2021/09/19 07:13

単にreturnすると厳しいかもしれないからグローバル変数とか使った方がいいかもしれない。
Avent

2021/09/19 07:38

ああ、そういえばsetTimeout(() => {})の{} って関数でしたね。。。 質問し直します!回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問