## <font class="h2">自動排程settimeout與 setInterval()</font>
###### tags: `javascript`
<style>
.h2 {
background: linear-gradient(135deg,#fff,#537479) ;
color: #537479;
display:block;
padding: 6px 5px;
border-radius: 4px;
}
.h3 {
background: linear-gradient(180deg,#fff 50%,#c9d5d4) ;
color: #537479;
display:block;
padding: 6px 5px;
border-bottom: 3px solid #537479;
}
.h4 {
color: #537479;
font-weight:bold;
font-size:1.1em;
}
</style>
:::info
javascript是同步語言,中間有報錯程式就不會繼續跑
:::
雖然setTimeout()這些timer方法不在ECMAScript的規格內,而==是屬於window的方法==,也就是BOM的一部分,不過多數瀏覽器與Node.js也都有實作這些timer方法,根據環境不同實作也多少有些差異,像是==瀏覽器的setTimeout/setInterval回傳的是Number,而在Node.js回傳的是Object。==
<br>
| 語法 |內容 |
| ------------ | ------------------ |
| setTimeout() | 只會執行一次就結束 |
| setInterval()| 在間隔固定的時間不斷重複 |
<br>
### <font class="h4">句法:</font>
:::info
```javascript
var timeoutID = scope.setTimeout(function[, 毫秒, param1, param2, ...]);
var timeoutID = scope.setTimeout(function[, 豪秒]);
var timeoutID = scope.setTimeout(code[, 豪秒]);//code可以為字串
```
`[]`代表可以省略不寫
:::
<br>
### <font class="h3">setTimeout()</font>
### <font class="h4">➤範例一.</font>
```javascript
let timeoutID =setTimeout(function(){console.log("Hello")},3000);
```
或
```javascript
let timeoutID = window.setTimeout(( () => console.log("Hello!") ), 1000);
```
<br>
### <font class="h4">➤範例二.</font>
秒數後面,可以帶入參數

<br>
### <font class="h4">➤範例三.</font>
```javascript
function showLog(){
console.log('倒數計時')
}
setTimeout(showLog,1000)
```
<br>
### <font class="h4">➤倒數計時範例:</font>


但數字不會停下來
<br>

可以使用if判斷停下來
<br><br><br><br>
### <font class="h4">➤`clearTimeout()`</font>
當我們呼叫setTimeout()與setInterval()的時候,它們會回傳一個獨立的timeID,這個ID就是當我們想取消setTimeout()與setInterval()的時候作為識別的數字。
<br><br><br>
```javascript
let timeoutID = window.setTimeout(( () => console.log("Hello!") ), 1000);
window.clearTimeout(timeoutID);
```
<br><br><br>
### 範例:
```javascript
setTimeout( () => {
console.log('倒數計時')
},5000)
```

會得到一個id數字,可以使用`clearTimeout()`來暫停setTimeout函式
<br><br>
```javascript
setTimeout( () => {
console.log('倒數計時')
},5000)
clearTimeout(2)
```
### <font class="h3">setTimeout 遇到迴圈: IIFE範例</font>
```javascript
for( var i = 0; i < 5; i++ ) {
window.setTimeout(function () {
console.log(i);
}, 1000*i);
}
```
但是上面這段 code 執行的結果是, console.log() 會在「一秒鐘之後」同時印出「五次 5」。
這是為什麼呢? 由於 JavaScript 切分變數有效範圍 (scope) 的最小單位為 function,所以當 1000ms 過去, 變數 i 的值早已是 for 迴圈更新完畢的 i ,而不是迴圈內當下的那個 i
<br>
```javascript
for (var i = 0; i < 5; i++) {
// 為了凸顯差異,我們將傳入後的參數改名為 x
(function (x) {
window.setTimeout(function () {
console.log(x);
}, 1000 * x);
})(i);
}
```

使用立即函式,就可以解決這個問題
<br>
```javascript
for( let i = 0; i < 5; i++ ) {
window.setTimeout(function () {
console.log(i);
}, 1000*i);
}
```
也可以使用let避開這個問題。
<br><br><br><br>
### <font class="h3">setInterval()</font>
setInterval盡可能不要重複執行
### <font class="h4">範例:</font>
```javascript
let timeoutID = window.setInterval(( () => console.log("Hello!") ), 1000);
```
`setInterval() `一啟動之後就會在固定的間隔時間不斷執行
如果想要停下來,就需要用到 `clearInterval()` 來取消 `setInterval()`。
```javascript
let timeoutID = window.setInterval(( () => console.log("Hello!") ), 1000);
window.clearInterval(timeoutID);
```
<br>
### <font class="h4">➤`clearInterval()`</font>
`clearInterval()`可以暫停setInterval函式
### 語法:
```javascript
clearInterval(timeoutID)
```
<br><br><br><br>
### <font class="h3">紀錄停止編號(timeoutID)範例</font>
透過改寫javascript的方式,將setInterval的編號給紀錄下來
```javascript
window._setInterval = window.setInterval;
window.setInterval = function(fun,time,...args){
window._setIntervalQueue = window._setIntervalQueue ||[];
let sid = window._setInterval(fun,time,...args);
window._setIntervalQueue.push(sid);
return sid;
}
window.clearIntervalAll = function(){
while(window._setIntervalQueue.length){
let sid = window._setIntervalQueue.shift();
window.clearInterval(sid)
}
}
```

### 說明:


<br><br><br><br>
```javascript
setInterval(function(){
console.log(Date.now())
},5000)
_setIntervalQueue //就可以查看編號
clearIntervalAll() //setInterval就會停止了
```
<br><br><br><br>
### <font class="h3">其他</font>
setTimeout可以取用全域的變數
```javascript
const a = 'hello'
function aaa() {
setTimeout(function () {
console.log(a)
}, 1000)
}
aaa() //hello
```
---
[latentflip測試Stack Queue狀態](http://latentflip.com/loupe/?code=!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D)
https://ithelp.ithome.com.tw/articles/10007614
https://www.youtube.com/watch?v=d50tamoZa-M&ab_channel=DansonLin
https://www.youtube.com/watch?v=60RkpSQYl_0&ab_channel=%E5%AE%89%E8%BF%AATV%23AndysTV-%E7%BE%8E%E9%A3%9F%2C%E7%A8%8B%E5%BC%8F%2C%E7%A7%91%E6%8A%80%2C%E8%BB%9F%E7%B6%B2
https://kuro.tw/posts/2019/02/23/%E8%AB%87%E8%AB%87-JavaScript-%E7%9A%84-setTimeout-%E8%88%87-setInterval/
https://ithelp.ithome.com.tw/articles/10227121
https://autoposter.pixnet.net/blog/post/116854913-js-%E4%B8%ADsettimeout%28%29%E7%9A%84%E7%94%A8%E6%B3%95%E8%A9%B3%E8%A7%A3
https://www.youtube.com/watch?v=I93LFPtBgL8&t=131s&ab_channel=%E5%BD%AD%E5%BD%AD%E7%9A%84%E8%AA%B2%E7%A8%8B