iT邦幫忙

0

如何使clearTimeout正常運作,以隨時取消(中斷)setTimeout循環?

我正使用Node.js製作一個Raspberry Pi的GPIO的控制應用,可以接收LoRa模組傳過來的封包,並針對封包內容控制GPIO開關,主要有三個功能
1.GPIO開啟
2.GPIO關閉
3.將GPIO開啟一段設定時間後自動關閉(使用Javascript setTimeout,在設定時間後呼叫GPIO關閉的函式)

這三個功能都正常運作。

現在的問題在setTimeout函式,在setTimeout循環中,想要隨時能終止它(例如設定15秒後關閉GPIO,但想要提前終止setTimeout)。

嘗試用了clearTimeout,似乎沒有作用(中途呼叫關閉GPIO的函式,必須等到15秒後同時得到兩個輸出),附上程式輸出及程式碼片段,請教各位大大問題出在哪邊?

程式輸出:

// timeout單位為毫秒
// 打開GPIO 15 秒,呼叫deviceTurnOn(15000)
Received:0, the solenoid valve has been opened!                                
Received packet: !20!96 0 0 0 53 0 0 28 11 3 TurnOn15s RSSI: -40 SNR:   6

// setTimeout的輸出,15秒時間到後自動呼叫deviceTurnOff()函式
Received:1, the solenoid valve has been closed!                                 

// 中途呼叫deviceTurnOff()函式
Received:1, the solenoid valve has been closed!                                
Received packet: !18!96 0 0 0 53 0 0 29 9 3 TurnOff RSSI: -41 SNR:   7 

程式碼:


var turnOffTimeout;

// 打開GPIO
function deviceTurnOn(timeout) {


    // 檢查是否帶關閉延遲時間
    if (timeout == -1) {
        console.log(`Received:0, the solenoid valve has been opened!`);
        // 控制GPIO開啟
        OutputDevice.writeSync(0);
    } 
    else {

        // 帶關閉延遲時間time
        console.log(`Received:0, the solenoid valve has been opened!`);
        // 控制GPIO開啟
        OutputDevice.writeSync(0);

        // 清除存在的計時器
        clearTimeout(turnOffTimeout);

        // 設定延遲
        turnOffTimeout = setTimeout(deviceTurnOff, timeout);
    }
}

// 關閉GPIO
function deviceTurnOff() {

    console.log(`Received:1, the solenoid valve has been closed!`);
    // 控制GPIO關閉
    OutputDevice.writeSync(1);
    // 清除計時器
    clearTimeout(turnOffTimeout);
}

1 個回答

1
浩瀚星空
iT邦大師 1 級 ‧ 2019-04-01 10:06:19

從程式來看倒是看不出什麼大問題。唯一一個程式碼我是建議拉上來
就是deviceTurnOn()內的clearTimeout。可以將其放在一開始的前頭來。
確保每一次運行ON(無論有無時間)都會確定其clearTimeout的運行,不至於造成2次setTimeout

這可能是我認為你唯一的問題了。

看更多先前的回應...收起先前的回應...
er0603 iT邦新手 5 級 ‧ 2019-04-02 01:54:10 檢舉

您好,嘗試使用您的建議修改程式,問題依舊無法解決耶?程式輸出與修改前相同(都要15秒後才會同時得到兩筆的輸出)
是否還有其他的建議呢?

基本上這段程式沒什麼問題,那就看你其它因素了。
如果可以的話。可以將

turnOffTimeout = setTimeout(deviceTurnOff, timeout);

先改成

turnOffTimeout = setTimeout(function(){
   console.log(`timeout!!`);
   deviceTurnOff();
}, timeout);

來跑看看,並看其輸出訊息的情況。

er0603 iT邦新手 5 級 ‧ 2019-04-02 22:58:20 檢舉

您好,謝謝您的建議,之前有嘗試過這樣的寫法,console.log裡面的東西15秒後才會印出來,狀況和現在的問題一樣,無法隨時終止turnOffTimeout。附上全部的程式碼,若您有興趣也可以看看,謝謝https://jsbin.com/vimawifutu/1/edit?js

er0603 iT邦新手 5 級 ‧ 2019-04-02 23:05:20 檢舉

簡單描述程式的流程大致上是:
1.透過LoRa模組接收訊息,判斷訊息封包內容是否包含TurnOn、TurnOff、TurnOn{時間}
2.依據訊息封包內容呼叫TurnOn、TurnOff對應的Function
3.對硬體GPIO進行控制

這些功能目前都正常,唯獨隨時終止turnOffTimeout是有問題的,或許是其他程式寫法影響到?

我要發表回答

立即登入回答