Delayed Function Calls

How do I delay a function call for 5 seconds?

You can use plain javascript, this will call your_func once, after 5 seconds:

setTimeout(function() { your_func(); }, 5000);

If your function has no parameters and no explicit receiver you can call directly setTimeout(func, 5000)

There is also a plugin I've used once. It has oneTime and everyTime methods.

  • jQuery timers plugin

Delayed function calls

Thanks to modern C# 5/6 :)

public void foo()
{
Task.Delay(1000).ContinueWith(t=> bar());
}

public void bar()
{
// do stuff
}

Delay function execution if it has been called recently

The question

Like a debouncer, you don't want to immediately execute on each call. But unlike a debouncer, you want to have each call queued for future execution.

Like a scheduler, you want to specify when to call the queued calls. More specifically, you want to execute calls with a fixed delay inbetween each call.

This means we can take inspiration from different ideas:

  • From debouncers: How to not execute on every call.
  • From queues: How to organize calls (first-in-first-out (FIFO) is what we want).
  • From schedulers: How to manage calls.

With async/await

Using async/await is a great idea! Note that in JS there is no way to sleep() natively because of its original synchronous design. We could either implement sleep() synchronously by spinning (highly discouraged because it will make your site unresponsive) or asynchronously with Promises.

Example of how a sleep() function can be implemented asynchronously:

function sleep(milli) {
return new Promise(resolve => setTimeout(resolve, milli));
}

Now, to refactor your code to use async/await, we mostly only need to inline the setTimeout() function. Simply put, until the setTimeout() call we can do as usual, then sleep() for the specified time (1000 milliseconds), and then inline the callback:

function sleep(milli) {
return new Promise(resolve => setTimeout(resolve, milli));
}
let available = true;
let requested = 0;
async function notTwiceASecond() {
if (available) {
available = false;

console.log("Executed");
// ...

await sleep(1000);
available = true;
if (requested) {
--requested;
notTwiceASecond();
}
} else {
++requested;
}
}

for (let i = 0; i < 3; ++i) {
console.log("called");
notTwiceASecond();
}

Delay between different function calls

I've tested this based on "How to Make Decorators Optionally Turn On Or Off" (How to Make Decorators Optionally Turn On Or Off)

from time import sleep

def funcdelay(func):
def inner():
func()
print('inner')
sleep(1)
inner.nodelay = func
return inner

@funcdelay
def my_func1():
print("Function 1")

@funcdelay
def my_func2():
print("Function 2")

@funcdelay
def my_func3():
print("Function 3")
my_func1()
my_func2()
my_func3()
my_func1.nodelay()
my_func2.nodelay()
my_func3.nodelay()

Output:

Function 1
inner
Function 2
inner
Function 3
inner
Function 1
Function 2
Function 3

You can see that it can bypass the delay.

Delay-execute any existing function by a call of the form function_name.callAfter(ms, param1, param2, ...)

You can do it by adding a method to the function constructor's prototype object. That way any created function can inherit that method. It's referred to as prototypal inheritance:

Function.prototype.callAfter = function(delay, ...args) {
setTimeout(() => this(...args), delay)
};

Merging multiple identical delayed function calls

Have your async calls all execute a function, passing a deadline parameter, and also update a property storing the last deadline sent.

Your function will check the deadline parameter received against the last called deadline. If they don't match, it means that there was a more recent press of the button, so ignore that execution. If they match, then you can execute.

Here's a little example you can plug into a new SwiftUI single view app. Even if you don't know SwiftUI, it should be fairly clear what's going on.

Every time the button is pressed, it will reset the deadline. No matter how many times you press the button, you can see it only executes the print function (and changes the colour of the button), after 2 seconds without a press.

struct ContentView: View {

@State public var buttonSelected = false

@State private var lastDeadline = DispatchTime.now()

func delayedUpdate(when currentDeadline: DispatchTime) {

guard currentDeadline == lastDeadline else {
return
}
print("Delayed Action!")
self.buttonSelected.toggle()
// Do your self.updateUI() or whatever else here.
}

var body: some View {
Button(action: {
let deadline = DispatchTime.now() + 2.0
self.lastDeadline = deadline
DispatchQueue.main.asyncAfter(deadline: deadline, execute: {
self.delayedUpdate(when: deadline)
})
}) {
Text("Delayed")
.padding()
.foregroundColor(.white)
.background(self.buttonSelected ? Color.blue: Color.green)
.clipShape(Capsule())
}

}
}

Long delay function call in python?

Instead of using manual multi threading, why don't you consider using Async.io to do long running functions.

This approach is only available from Python 3.7+ but is more effective and efficient and requires less coding. Here is an in depth tutorial on how to use it

To delay JavaScript function call using jQuery

Since you declare sample inside the anonymous function you pass to ready, it is scoped to that function.

You then pass a string to setTimeout which is evaled after 2 seconds. This takes place outside the current scope, so it can't find the function.

Only pass functions to setTimeout, using eval is inefficient and hard to debug.

setTimeout(sample,2000)


Related Topics



Leave a reply



Submit