2017-07-28 57 views

回答

1

這裏最簡單的方案是隻是把你的代碼中,你與setTimeout()使用,如果計時器仍在運行,則取消計時器和直接調用該函數的函數:

function doSomeTask() { 
    // code here for your task 
} 

// schedule task to run in 20 seconds 
// remember timer handle so we know it's running 
let timer = setTimeout(() => { 
    timer = null; 
    doSomeTask(); 
}, 20*1000); 

// elsewhere in your code where you want to call your function 
// earlier than the timer (if it hasn't already been called) 
if (timer) { 
    clearTimeout(timer); 
    timer = null; 
    doSomeTask(); 
} 

承諾可以在這裏提供一些好處,因爲他們已經確保給定的承諾只能解決或拒絕一次,並可以在這裏利用。爲了優雅地使用它們,我可能會創建一個小狀態對象,使它非常易於使用。

function delayExecute(fn, t) { 
    let obj = {state: "timer"}; 
    let p = new Promise((resolve, reject) => { 
     obj.runNow = resolve; 
     obj.cancel = reject; 
     setTimeout(resolve, t); 
    }).catch(err => { 
     obj.state = "err"; 
     throw err; 
    }).then(() => { 
     fn(); 
     obj.state = "done"; 
    }); 
    return obj; 
} 

function doSomeTask() { 
    // code here for your task 
} 

let task = delayExecute(doSomeTask, 20*1000); 

// then some time later, to run it sooner (if it hasn't already run) 
// calling the .runNow() method after the function has already run will do nothing 
task.runNow(); 

這個相同的接口也可以沒有承諾建立。我只是想我會展示如何利用一些承諾的單向狀態轉換來實現此目的。

+0

絕對是最直接的方法。在我看來,承諾對於這個特殊問題是過分的。 +1 –

+0

@PatrickRoberts - 我添加了一個基於承諾的實現,僅僅是爲了展示如何幹淨地完成它。這裏肯定不需要承諾,但他們做了一些有用的事情,可以在這裏使用。 – jfriend00

+0

不錯的更新,但是你的'cancel()'實際上並沒有取消:P哦,等等,我去了。這是一種奇怪的做法,我本可以做一些有點不同的事情,但確實有效。 –

0

你有幾個選擇來做到這一點。由於您沒有包含任何關於如何管理併發的代碼或信息,因此我會向您展示一種使用承諾似乎合理的方式。

let resolve; 
let promise = new Promise(res => resolve = res); 

// function to call after max 2s or after response 
let fn =() => { 
    console.log(process.uptime(), 'Function called'); 
}; 

// the timeout: 
setTimeout(resolve, 1000); 

// the fake response handler: 
setTimeout(() => { 
    console.log(process.uptime(), 'Request returned'); 
    resolve(); 
}, 2000 * Math.random()); 

promise.then(fn); 

then處理程序將只運行一次。執行此程序多次,您會看到該函數在假響應處理程序被調用後立即被調用(如果在1秒超時觸發之前調用該函數),或者如果超時爲第一個,則立即在超時之後調用該函數。

相關問題