1

I am running a loop & within the loop I am calling a function. The function makes an ajax call & returns response but the problem is loop is not waiting for the response therefore the function returns undefined.

function checkBidStatus(index) {
  $.ajax({
     type:'get',
     url:'/orderbook/checkorderdetails',
     success: function(data){
        $parsedData = JSON.parse(data);
        if($parsedData[index]) {
          return "Hello";
        } else {
          return "Bye";
        }

        //$("#bid-details .modal-dialog").html(data);
     },
    error: function (response) {
      console.log(response);
    }
  });
}

let content = '';
 for(let i = 1; i <= 10; i++ ) {
    content += '<div>' + 
    (checkBidStatus(i)) +
    '</div>';
 }
9
  • 1
    The problem is that the for loop is synchronous, but the ajax call is asynchronous. I.e., that function has to wait for the server to respond. Therefore, callbacks or promises need to be used by the caller before iterating to the next request. Commented Apr 2, 2019 at 5:43
  • plz elaborate with code Commented Apr 2, 2019 at 5:46
  • Ok... in progress. Code coming soon. Commented Apr 2, 2019 at 5:48
  • You can make the ajax call synchronous, by defining the async:false in ajax body. this is the easy solution but it also block your ui thread, that means your ui will non responding during the loop. Commented Apr 2, 2019 at 5:55
  • 1
    @ayan_84 synchronous Ajax is deprecated due to the poor user experience it provides. It locks the browser during use and a long running request (or series of requests) can give the user the impression that the page has crashed. Also since it's deprecated you can expect browsers to stop supporting it in the foreseeable future. This is not a good way to solve the problem. Promise chaining would be a more suitable solution Commented Apr 2, 2019 at 5:58

3 Answers 3

2

The problem is that the for loop is synchronous, but the ajax call is asynchronous. I.e., that function has to wait for the server to respond. Therefore, callbacks or promises need to be used by the caller before iterating to the next request.

There are elegant ways to accomplish this task using certain libraries, such as async, but the "quick vanillaJS" way to solve this task using promises would be something like this:

const contentTemplate = '<div>[BID_RESULT]</div>';
const nRequests = 10;
var requestCnt = 0;
var content = '';

function checkBidStatus(index) {
    return new Promise((resolve, reject) => {
        $.ajax({
            type:'get',
            url:'/orderbook/checkorderdetails',
            success: function(data){
               $parsedData = JSON.parse(data);
               resolve({ index: index + 1, msg: $parsedData ? "Hello" : "Bye" });
            },
            error: reject
        });
        // <-- NOTE: there is no return statement at this line. Hence if 
        // you were to call this function from your for loop, you'd see 
        // undefined
    }
}

Then, you can keep calling that function recursively:

function multipleRequests(){
    checkBidStatus(requestCnt)
    .then((resp) => { // This runs if the promise RESOLVES (i.e., success)
        content = contentTemplate.replace('[BID_RESULT]', resp.msg);
        // --- [then do what you want with content] --- //
        // Request again
        requestCnt++;
        if( requestCnt < nRequests ){
            multipleRequests();   
        }
    })
    .catch(console.error) // This runs if promise rejects (i.e., has an error)
}

// Run:
multipleRequests();
Sign up to request clarification or add additional context in comments.

Comments

1

Why not use a Promise inside and wait on that promise to get the required result, after which you update the DOM? In your checkBidStatus method, you can create a promise and return that. When the ajax result is available, resolve the promise with ajax result.

The caller of the method would need to wait for the promise to resolve and then update the DOM.

let content = '';
for(let i = 1; i <= 10; i++ ) {
  checkBidStatus(i).then(result => {
    content += '<div>' +result + '</div>';
  })
}

Note: I have not tested the code, but something similar should work. Also the order of divs created base on the index is not guaranteed, so you may need to take care of that, if order is important.

1 Comment

I think this pretty nice. I think a combination of our answers should get him going :)
0

You should wait till response from server for every iteration in loop.

function checkBidStatus(index) {
$.ajax({
    type: 'get',
    url: '/orderbook/checkorderdetails',
    success: function(data) {
        $parsedData = JSON.parse(data);
        if ($parsedData[index]) {
            return {
                msg: 'Hello',
                index: index + 1,
            };
        } else {
            return {
                msg: 'Bye',
                index: index + 1,
            };
        }

        //$("#bid-details .modal-dialog").html(data);
    },
    error: function(response) {
        console.log(response);
    },
});

}

let content = '';
let i = 1;
while (i <= 10) {
    let { msg, index } = checkBidStatus(i);
    content += '<div>' + msg + '</div>';
    i = index;
}

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.