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

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

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

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

Q&A

解決済

1回答

2851閲覧

JavascriptのsetTimeout(setInterval)のタイミングがずれる

oyatsu8

総合スコア97

JavaScript

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

0グッド

0クリップ

投稿2018/11/25 09:49

JavascriptのsetTimeoutのタイミングがずれて行く。

やろうとしたことは

  • リストページを開いた時にデフォルトでテスト01が選択されていて、最初に3秒間「1をを表示」を表示し、その後に「1を終了」
  • テスト01、テスト02、テスト03のボタンをクリックした時に、クリックした時点から最初に3秒間「〜を表示」を表示し、その後に「〜を終了」

です。

下記のコードで「テスト01」をクリックすると、最初に「1をを表示」3秒後に「1を終了」というメッセージが出るように作ったのですが、何度かクリックしているうちに、すぐに「1を終了」が出てタイミングが3秒よりかなり短くなってしまいます。一回一回の挙動に対して、clearIntervalをしないといけないと書いてあったので、
clear_setTime_aという関数を作り、setTime_a()の中に埋め込んでみたのですが、やはりタイミングがおかしくなってしまいました。
その後、setIntervalにしていたのをsetTimeoutに変えてみたのですが、やはり挙動がおかしくなってしまいました。

アドバイスを頂けたら助かります。

html,javascript

1<!DOCTYPE html> 2<html lang='ja'> 3<head> 4<meta http-equiv="Content-Type" content="application/javascript; charset=utf-8"/> 5<style type="text/css"> 6<!-- 7.mizu{ 8 background: #9FF; 9} 10//--> 11</style> 12 13<meta name="viewport" content="width=device-width, initial-scale=1"> 14 <title>setIntervalテスト</title> 15 <script src="js/jquery-3.3.1.min.js"></script> 16</head> 17 18<body> 19 <ul id="sw"> 20 <li id="sw01" class="mizu"> 21 テスト01 22 </li> 23 <li id="sw02"> 24 テスト02 25 </li> 26 <li id="sw03"> 27 テスト03 28 </li> 29 </ul> 30<div id="textPlace"></div> 31 32<script type="text/javascript"> 33var on_no = '1'; 34var txt01 = "1"; 35const $li = document.querySelectorAll('#sw>li'); 36document.querySelector('#sw').onclick = e => { 37 if(e.target === e.currentTarget) return; 38 let item = e.target.closest('li'); 39 on_id = item.getAttribute("id"); 40 if(on_id == 'sw01'){ 41 on_no = '1'; 42 }else if(on_id == 'sw02'){ 43 on_no = '2'; 44 }else if(on_id == 'sw03'){ 45 on_no = '3'; 46 } 47 setTime_a(); 48 $li.forEach(n => n.classList[item === n ? 'add':'remove']('mizu')); 49}; 50 51txt01 = document.getElementById("textPlace"); 52txt01.innerHTML = on_no + "を表示"; 53setTime_a(); 54 55function setTime_a(){ 56 //setInterval(function(){ 57 setTimeout(function(){ 58 txt01.innerHTML = on_no + "を終了"; 59 console.log("setIntervalしたつもり"); 60 61 clear_setTime_a(); 62 },3000); 63 txt01.innerHTML = on_no + "を表示"; 64 console.log("3秒"); 65} 66 67function clear_setTime_a(){ 68 clearInterval(setTime_a); 69 console.log("clearIntervalしたつもり"); 70} 71 72</script> 73</body> 74</html> 75 76

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

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

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

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

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

guest

回答1

0

ベストアンサー

修正案

html

1<!DOCTYPE html> 2<html lang='ja'> 3<head> 4<meta http-equiv="Content-Type" content="application/javascript; charset=utf-8"/> 5<style type="text/css"> 6 .mizu{ 7 background: #9FF; 8 } 9</style> 10 11<meta name="viewport" content="width=device-width, initial-scale=1"> 12 <title>setIntervalテスト</title> 13 <script src="js/jquery-3.3.1.min.js"></script> 14</head> 15 16<body> 17 <ul id="sw"> 18 <li id="sw01" class="mizu"> 19 テスト01 20 </li> 21 <li id="sw02"> 22 テスト02 23 </li> 24 <li id="sw03"> 25 テスト03 26 </li> 27 </ul> 28<div id="textPlace"></div> 29 30<script type="text/javascript"> 31var on_no = '1'; 32var txt01 = "1"; 33const $li = document.querySelectorAll('#sw>li'); 34document.querySelector('#sw').onclick = e => { 35 if(e.target === e.currentTarget) return; 36 let item = e.target.closest('li'); 37 on_id = item.getAttribute("id"); 38 if(on_id == 'sw01'){ 39 on_no = '1'; 40 }else if(on_id == 'sw02'){ 41 on_no = '2'; 42 }else if(on_id == 'sw03'){ 43 on_no = '3'; 44 } 45 setTime_a(); 46 $li.forEach(n => n.classList[item === n ? 'add':'remove']('mizu')); 47}; 48 49txt01 = document.getElementById("textPlace"); 50txt01.innerHTML = on_no + "を表示"; 51setTime_a(); 52 53// 以前の timeoutID を保持する変数 54var prev_timeout_id = null 55function setTime_a(){ 56 // timeout がすでに設定されている場合取り消す。 57 if (prev_timeout_id != null){ 58 clearTimeout(prev_timeout_id) 59 console.log("clearTimeout しました。") 60 } 61 62 // timeoutID を保存 63 prev_timeout_id = setTimeout(function(){ 64 txt01.innerHTML = on_no + "を終了"; 65 },3000); 66 txt01.innerHTML = on_no + "を表示"; 67} 68</script> 69</body> 70</html>

説明

連続で選択対象を切り替えた際に、予定より早く切り替わってしまうのは以前に設定されたタイムアウトをキャンセルできていないことが原因だと思われます。
修正案では別項目が選択された際に以前のタイムアウトが設定されている場合それをキャンセルしたあとでタイムアウトを設定し直すように変更してみました。

参考リンク

setTimeout
clearTimeout

投稿2018/11/25 10:26

編集2018/11/25 10:29
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

oyatsu8

2018/11/25 11:58

大変ありがとうございました。うまく動くようになりました。setTimeoutがこんなに複雑だとはおもっていませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問