3 functions, execute each one after 1500 milliseconds

Hey guys,

Ok so got an issue I cannot seem to solve. I have an API I am querying via JQuery AJAX. I have 3 functions that perform different checks (username, email address and password) but as the API has recently been rate limited, it only allows queries every 1500 milliseconds. The functions are as follows:-

checkusername(username);
checkemail(email);
checkpassword(password);

They are all checked against the HaveIbeenpwned API but neither setTimeout or setInterval are working in my code and I’m close to tearing out my hair on this one as the API is still spitting back code 429 which is for rate limit exceeded. I’ve tried the following:

setTimeout(checkusername(username), 1500);
setTimeout(checkemail(email), 1500);
setTimeout(checkpassword(password), 1500);

That doesn’t work! Has anyone any ideas? As said I need it to wait 15 milliseconds between firing each function;

Thanks in advance for any help!

I’m not 100%, but I think if that’s the way you have your timeouts set, they’ll all run pretty much in parallel. The 2nd timeout won’t wait until the first is completed, and neither will the third.

You might want to look at this on promises - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

Aha! I had a feeling that might be the case. See this is what I hate about rate limited API’s as there is no proper client side way of firing functions with a delay between each one because as you have said one is firing after the other and not waiting and I don’t know any other way of doing it.

Let’s see if we can solve this from the outside in.

What might help is to store the functions that we want to run in an array. The params to the function could be stored in there too.

After developing this idea, the following code seem like it might do the job:

var delayedFuncs = [];
function triggerNextDelayedFunc() {
  if (delayedFuncs.length < 1) {
    return;
  }
  var delayedFunc = delayedFuncs.shift();
  var func = delayedFunc.func;
  var params = delayedFunc.params;
  var delay = 1500;
  setTimeout(triggerWrapper(func, params), delay);
}

While putting that code together, it became natural to refer to the function and the parameters of the delayedFunc object as separate parts, in the following kind of structure:

{
    func: someFunc,
    params: [param1, param2]
}

The timeout requires a function, so we can return a function from the triggerWrapper.

function triggerWrapper(func, params) {
    return function () {
        ...
    };
}

That returned function is from where we’ll run the func with its parameters.
After it’s finished running, we’ll want to also run the triggerNextDelayedFunc() function again.

function triggerWrapper(func, params) {
    return function () {
        func.apply(params);
        triggerNextDelayedFunc();
    };
}

We should now be able to add the username/email/password to the array.

delayedFuncs.push({
  func: checkusername,
  params: [username]
});
delayedFuncs.push({
  func: checkemail,
  params: [email]
});
delayedFuncs.push({
  func: checkpassword,
  params: [password]
});

It would be better if we used a separate function to add each delayed function, so that we can just pass it the name of the function and an array of parameters.

function addDelayedFunc(func, params) {
  delayedFuncs.push({
    func: func,
    params: params
  });
}
addDelayedFunc(checkusername, [username]);
addDelayedFunc(checkemail, [email]);
addDelayedFunc(checkpassword, [password]);

After adding some fake functions to do the username/email/password stuff, we end up with the following code

1 Like

Just tried out how little code it takes to make this possible with ES7 async await:

I’m impressed :slight_smile:
This is what I have come up with:

async function sleep(fn, ms) {
    await new Promise(resolve => setTimeout(resolve, ms))
    fn()
}

async function doStuff() {
	await sleep(validateEmail, 1500)
	await sleep(validateEmail, 1500)
	await sleep(validateEmail, 1500)
	document.body.innerHTML += '<hr>'
}

function validateEmail() {
	document.body.innerHTML += '<br>'+new Date().getTime()
}
1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.