在一次执行结束后等待指定间隔再执行下次
--see-also https://developer.mozilla.org/zh-CN/docs/Web/API/Window/setInterval
1 const loop = (firstNoDelay, delay, callbackFn) => { 2 // firstNoDelay : true 立即执行第一次 3 // delay 单位毫秒 4 const wrappedCallback = () => { 5 try { 6 callbackFn(); 7 return []; 8 } catch (err) { 9 return [ err ]; 10 } 11 }; 12 13 let running = true; 14 let timer = null; 15 const loopInner = () => { 16 timer = setTimeout(() => { 17 if (running) { 18 wrappedCallback(); 19 loopInner(); 20 } 21 }, delay); 22 } 23 24 const firstPromise = firstNoDelay ? new Promise((resolve, reject) => { 25 return resolve(wrappedCallback()); 26 }) : Promise.resolve([]); 27 28 firstPromise.then((r) => { 29 // console.log('[DEBUG] loop result of first', r); 30 loopInner(); 31 return 0; 32 }); 33 34 return () => { 35 running = false; 36 const t = timer; 37 if (t == null) { 38 console.log("no timer"); 39 } else { 40 timer = null; 41 console.log("clear timer", t); 42 clearTimeout(t); 43 } 44 }; 45 };
html 示例
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>test recurse timeout</title> 5 </head> 6 <body> 7 <button id="startBtn">start</button> 8 <button id="stopBtn">stop</button> 9 <div id="testDiv"></div> 10 11 <script> 12 const loop = (firstNoDelay, delay, callbackFn) => { 13 // firstNoDelay : true 立即执行第一次 14 // delay 单位毫秒 15 const wrappedCallback = () => { 16 try { 17 callbackFn(); 18 return []; 19 } catch (err) { 20 return [ err ]; 21 } 22 }; 23 24 let running = true; 25 let timer = null; 26 const loopInner = () => { 27 timer = setTimeout(() => { 28 if (running) { 29 wrappedCallback(); 30 loopInner(); 31 } 32 }, delay); 33 } 34 35 const firstPromise = firstNoDelay ? new Promise((resolve, reject) => { 36 return resolve(wrappedCallback()); 37 }) : Promise.resolve([]); 38 39 firstPromise.then((r) => { 40 // console.log('[DEBUG] loop result of first', r); 41 loopInner(); 42 return 0; 43 }); 44 45 return () => { 46 running = false; 47 const t = timer; 48 if (t == null) { 49 console.log("no timer"); 50 } else { 51 timer = null; 52 console.log("clear timer", t); 53 clearTimeout(t); 54 } 55 }; 56 }; 57 document.addEventListener("DOMContentLoaded", () => { 58 console.log("loaded"); 59 const testDiv = document.getElementById("testDiv"); 60 const startBtn = document.getElementById("startBtn"); 61 const stopBtn = document.getElementById("stopBtn"); 62 63 const loopTerms = []; 64 startBtn.addEventListener("click", () => { 65 startBtn.disabled = true; 66 const startTimeTxt = `${new Date()}` 67 const clearLoop = loop(true, 1000, () => {testDiv.innerText = `${startTimeTxt} \n ${new Date()}`}); 68 loopTerms.push(clearLoop); 69 }); 70 stopBtn.addEventListener("click", () => { 71 startBtn.disabled = false; 72 for (let clrLoop = loopTerms.shift(); clrLoop; clrLoop = loopTerms.shift()) { 73 clrLoop(); 74 } 75 }); 76 }); 77 </script> 78 </body> 79 </html>
--- THE END ---