user4333143
user4333143

Reputation:

Creating a "delay" function in JS?

I've been reading about setTimeout and other such timers. But I'm wondering if it's possible to work up a custom function so that all you would need to do is something like this:

//code
delay(time);
//more code

Is this possible?

UPDATE: Ok, I kind of get it. So if that isn't reasonably possible, how would you go about delaying a loop AFTER the first time. I want it to run immediately upon execution but they delay on each iteration afterward.

New UPDATE: I figure since my initial thought fell through, it might just be easier to show you the code I have.

function autoFarm (clickEvent){

var farmTargets = [
            "6_300_1",
            "6_300_3",
            "6_300_4",
            "6_300_5",
            "6_300_7"];


setTimeout(function() {
 $.each (farmTargets, function(index, target){     
    var extraData = '{"end_pos":"' + target + '","purpose":0,"upshift":1,"bring_res":{"0":0,"2":0,"1":0},"bring_ship":{"1":25,"11":0},"rate":100,"start_pos":"6_300_2"}';

var finalData = baseDataDora + extraData + "&type=1";

 setTimeout(function(){
    for (i = 0; i < farmTargets.length; i++){
        postRequest(sendFleetURL + getSign(extraData). finalData, function(json){               
        });             
    }       
 }, 15000); 
 });//End each loop
}, 1320000);    
}//End autoFarm

Basically, it should execute immediately and run the for loop 5 times on the first array element 15 seconds apart. Then 22 minutes later move to the next set and repeat for the entire array.

Upvotes: 1

Views: 1291

Answers (4)

Josep Vicent Ibanez
Josep Vicent Ibanez

Reputation: 1758

Using a Promise, calling it inside an asynchronous function.

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

const any_function = async() => {
   await delay(2000); 
   console.log('this log has been delayed 2 secs')
} 

Upvotes: 0

elclanrs
elclanrs

Reputation: 94121

You can achieve something along those lines with generators. The idea is that continuation passing style (callback hell) can be flattened. The generator uses the yield keyword to pause the function, until the callback resumes it by calling its next method:

var async = function(gen) {
  var g = gen()
  function next(x) {
    var cur = g.next(x)
    if (cur.done) {
      return cur.value
    }
    cur.value(next)
  }
  next()
}

var delay = function(time) {
  return function(f) {
    setTimeout(f, time)
  }
}

async(function* () {
  console.log('before')
  yield delay(1000) // waits one second
  console.log('middle')
  yield delay(1000) // waits one second
  console.log('after')
})

In CPS it would read something like:

console.log('before')
setTimeout(function() {
  console.log('middle')
  setTimeout(function() {
    console.log('after')
  }, 1000)
}, 1000)

This works in Chrome, Firefox and iojs today.

Upvotes: 1

zzzzBov
zzzzBov

Reputation: 179196

As-written, no that's not possible.

If, instead you were to use a queue, delays in that manner are trivial.

jQuery's .queue() and .delay() functions are a good example of how this works, so I will use them as an example, however the general point stands for any queueing library.

Instead of:

//code
delay(time)
//more code

With a queue, you'd write:

$('...') //some selector to act on for jQuery
.queue(function (next) {
    //code

    //Indicate that the queued call is finished.
    next();
    //This allows async code to be executed in the queue,
    //such as ajax and animations
})
.delay(time)
.queue(function (next) {
    //more code
    next();
});

Now, even if you ignore the lines used for comments, you can tell that there's a bit more boilerplate to achieve the desired behavior. I don't feel that it's excessive, because I find it relatively easy to read:

  1. queue something to happen
  2. wait for some number of milliseconds
  3. queue something else to happen

Upvotes: 0

brian
brian

Reputation: 2775

This isn't possible because of the way single-threaded event loops work. If this function were to exist, it would cause the entire UI thread to freeze until the delay was satisfied. setTimeout(cb, delay) is the nearest facility which schedules a function to be executed no earlier than the delay and at the end of the current event loop tick.

Update: Before somebody calls me on it, yes, you can theoretically engineer a delay function that freezes everything in place for a set amount of time. However, there is no reasonable excuse to do it this way.

To your second question:

function hello() {
    console.log('hello');
}

// execute immediately
hello();

// then every 5 seconds
setInterval(hello, 5000);

Upvotes: 0

Related Questions