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

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

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

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

非同期処理

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

Q&A

解決済

3回答

1973閲覧

非同期処理をループさせる方法。ポモドーロタイマーというやつで、25分⇒5分⇒25分⇒5分…と、指定回数繰り返します。

shimon_

総合スコア26

JavaScript

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

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

非同期処理

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

0グッド

0クリップ

投稿2020/03/30 14:13

#作りたいもの
タイマーのWebアプリを作っています。ポモドーロタイマーというやつで、タイマー(25分)⇒タイマー(5分)を1セットとし、{[25分⇒5分]⇒[25分⇒5分]…}と、指定回数分、カウントダウンを繰り返します。
#できていること
「25分⇒5分」といった、動作が一度だけでいい場合の処理は、Promiseで作ることができました。
下のコードでは、テスト用に、25分のところを25秒のように変えています。
#問題点
この非同期処理を、繰り返す、という部分で躓いています。Promise処理をループすることができれば、要件を満たせると思ったのですが、うまくいきません。

非同期処理を、同期的にループする方法、あるいは、要件を満たすための別の方法などがあれば教えていただければ助かります。

よろしくお願いします。

JavaScript

1// タイマーを表示する関数です 2function startTimer() { 3 // 繰り返し回数を取得する 4 var setCount = document.getElementById('setCount').value; 5 var dt = new Date(); 6 var timeLimit = new Date(dt.getTime() + 30 * 1000); // 30秒後 7 workTimer(timeLimit).then(() => { 8 console.log('workTimerが終了'); 9 restTimer(timeLimiti).then(() => { 10 console.log('restTimerが終了'); 11 }); 12 }); 13} 14// 残り時間(ms)を文字列に変換する関数です 15function returnTimeString(ms) { 16 var min = Math.floor(ms / 60000); 17 var sec = Math.floor((ms % 60000) / 1000); 18 min = ('0' + min).slice(-2); 19 sec = ('0' + sec).slice(-2); 20 return `${min}:${sec}`; 21} 22// workTimeを計算する関数です 23function workTimer(timeLimit) { 24 return new Promise((resolve) => { 25 var timer = setInterval(() => { 26 var now = new Date(); 27 var diff = timeLimit - now; 28 if (diff <= 5 * 1000) { 29 console.log('workTimer 停止'); 30 clearInterval(timer); 31 resolve(); 32 } else { 33 var timeString = returnTimeString(diff - 5 * 1000); // restTimeを引いた値を渡す 34 console.log(`workTimer: ${timeString}`); 35 } 36 }, 100); 37 }); 38} 39// restTimeを計算する関数です 40function restTimer(timeLimit) { 41 return new Promise((resolve) => { 42 var timer = setInterval(() => { 43 var now = new Date(); 44 var diff = timeLimit - now; 45 if (diff <= 0) { 46 console.log('restTimer 停止'); 47 clearInterval(timer); 48 resolve(); 49 } else if (diff > 0) { 50 var timeString = returnTimeString(diff); 51 console.log(`restTimer: ${timeString}`); 52 } 53 }, 100); 54 }); 55}

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

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

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

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

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

guest

回答3

0

ベストアンサー

TODOとしてはこんな感じですかね。

  • Promise使うならasync/await使おう
  • コピペ処理多すぎ問題の解決

async / await構文はPromiseを使う上で無くてはならないもので、
寧ろこれらの構文無しでPromise使うなんてメリット全く無いじゃん
レベルの必須さになっています。

確実に学習して使えるようにしておきましょう。
setIntervalは使いづらいので
setTimeout自体Promise化してasync/await構文として使い勝手が良いように変えていきます。

js

1// setTimeoutをPromiseでラッピングしただけ関数 2const sleep = ms => new Promise(resolve => 3 setTimeout(resolve, ms) 4); 5 6// await構文を使うためにasync関数を宣言する 7const start = async () => { 8 // setInervalじゃなくて無限ループにして使う 9 while (true) { 10 // awaitという糖衣構文により同期処理っぽいコードをthenのチェーンに変換してくれる 11 await sleep(3000); 12 console.log("3秒実行"); 13 await sleep(500); 14 console.log("0.5秒実行"); 15 } 16} 17 18start();

要するにこんな感じで解決出来るようになります。

質問文のコードからだと遠い道のりになりそうですが、
慣れればとても簡単に扱えるようになるので工夫してみてください。

投稿2020/03/31 00:41

miyabi-sun

総合スコア21203

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

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

shimon_

2020/03/31 11:17

ありがとうございました! 練習して、少しづつものにしていきます!
guest

0

「非同期処理を、同期的にループする」ことはできませんので、考え方を変える必要があります。
この場合であれば、restTimer(timeLimiti).then の中で startTimer() を呼べば良いのでは。

また、タイマーの処理でわざわざ Promise を使う必要はないと思います。(Promise の練習中だったらごめんなさい。)

投稿2020/03/30 21:57

hoshi-takanori

総合スコア7901

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

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

0

こんなふうではないでしょうか?

投稿2020/03/31 00:20

yambejp

総合スコア116720

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

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

yambejp

2020/03/31 00:20

var count=3; var first=5; var second=2; (async()=>{ console.log("start"); for(var i=0;i<count;i++){ await new Promise(r=>setTimeout(()=>r(),first*1000)); console.log(first); await new Promise(r=>setTimeout(()=>r(),second*1000)); console.log(second); } console.log("end"); })();
yambejp

2020/03/31 01:44

まあ普通にやるなら1秒ごと(or もっと小さく/大きく)に チェッカーを走らせ、想定時間をオーバーしたタイミングで 処理を走らせるので十分いけるとおもいますけどね 汎用性や管理しやすさを考えればsetIntarvalがベターだと思います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問