2

I have a function that I call from a from a timeout that makes an ajax call. I also have a button click call that I don't want to execute until the ajax call completes, if the ajax call is running. If the ajax call is not running, I want to run the button click code.

What is the best way to handle this? With a variable that you check to see if the ajax function is running or is there another way?

Here is my pseudo code

setTimeout(doAjax, 5000);

function doAjax() {
  $.ajax({
        url: "xxx.com/dosomething",
        dataType: 'json',
        type: 'POST',
        cache: false,
        contentType: 'application/json; charset=utf-8',
        success: function (data) { doSuccess() },
        error: function (data, status, jqXHR) { doError() }
    });
}

function myBtnClick() {
  // wait for doAjax call to complete if running
}
0

2 Answers 2

1

The solution here is to use promises to maintain the state of your async code.

let clickDelayPromise = Promise.resolve(); // initial value

async function myBtnClick() {
  // wait for the promise to resolve
  await clickDelayPromise;

  // now do stuff
}

function doAjax() {
  // assign the $.ajax deferred (promise) to the variable
  clickDelayPromise = $.ajax({
    // ...
  });
}

Initially, the clickDelayPromise will resolve immediately but once the AJAX call begins, the promise will only resolve once the request completes.

// mocks
const $ = {ajax:()=>(console.log("ajax starting"),new Promise(r=>setTimeout(()=>{console.log("ajax done");r();},4000)))};

let clickDelayPromise = Promise.resolve(); // initial value

async function myBtnClick() {
  // wait for the promise to resolve
  await clickDelayPromise;

  // now do stuff
  console.log("button click!");
}

function doAjax() {
  // assign the $.ajax deferred (promise) to the variable
  clickDelayPromise = $.ajax({
    // ...
  });
}

setTimeout(doAjax, 5000);
<button onclick="myBtnClick()">Click me lots</button>

Sign up to request clarification or add additional context in comments.

Comments

1

You can achieve what you want by making sure that your prerequisite async operations you have are promises and, if you have an array where you store them, then you can do something like this:

Promise.all(yourArray).then((values) => {
    /*Do something*/
})

Proof-of-concept:

function decreaseCounter() {
    let context = document.getElementById("counter");
    let value = parseInt(context.innerText);
    context.innerText = value - 1;
}
function test() {
    Promise.all(myPromises).then(() => {
        alert("Job Complete!");
    });
}
let myPromises = [
    new Promise(resolve => setTimeout(resolve, 1000)).then(decreaseCounter),
    new Promise(resolve => setTimeout(resolve, 2000)).then(decreaseCounter),
    new Promise(resolve => setTimeout(resolve, 3000)).then(decreaseCounter),
    new Promise(resolve => setTimeout(resolve, 4000)).then(decreaseCounter),
    new Promise(resolve => setTimeout(resolve, 5000)).then(decreaseCounter),
    new Promise(resolve => setTimeout(resolve, 6000)).then(decreaseCounter),
    new Promise(resolve => setTimeout(resolve, 7000)).then(decreaseCounter),
    new Promise(resolve => setTimeout(resolve, 8000)).then(decreaseCounter),
    new Promise(resolve => setTimeout(resolve, 9000)).then(decreaseCounter),
    new Promise(resolve => setTimeout(resolve, 10000)).then(decreaseCounter)
]
This is the final countdown:
<h1 id="counter">10</h1>

<b>Click on the button to see whether it waits for the countdown</b><br>
<input type="button" onclick="test()" value="Click Me">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.