5

i have js code which returns rows of data for my table. On clicking each of those rows they expand and plan is to show child data of that row by calling another ajax request.

My code for child data looks like below:

function format ( d ) {
    var results;
    $.ajax({ url: 'http://127.0.0.1:7101/MUDRESTService/rest/v1/feedbacks/' + 
    d.FeedbackId + '/child/MudFeedbackDetailsVO?onlyData=true',
            
             type: 'get',  
             dataType: 'json',    
             success: function(output) {
    console.log(output.items[0].CriticalPath) ; 
                        results =      output.items[0];        
                }
       
           });
    return  results.CriticalPath;
}

The problem probably is that method doesn't finish by the time value of results.CriticalPath is returned. I can see value in chrome js console so there is no problem with the data part.

So how should i make it return the value once the response is ready

x13
  • 2,179
  • 1
  • 11
  • 27
Vik
  • 8,721
  • 27
  • 83
  • 168
  • 1
    Use `Promise` maybe? – durrrr Nov 20 '15 at 08:41
  • I am also looking for a way of pausing the code or waiting for the result but i'm afraid it will either be impossible or near impossible. the asynchronous code is executed **after all** the synchronous code is executed so this will be extremely complicated. – x13 Nov 20 '15 at 08:42
  • No, you really *don't want* to block javascript execution and freeze your page. – Bergi Nov 20 '15 at 10:45

3 Answers3

1

When writing asynchronous code, you need to start working with callbacks rather than return values.

Your functions, like format here, only initiates an action. Updates to the UI are initiated by the callback.

Instead of this logic:

function doSomething() {
   var result = format(d);
   doSomethingWithResult(result);
}

You need to adapt to this:

function doSomething() {
   var result = format(d, doSomethingWithResult);
}

function format( d, callback ) {
   $.ajax(..., { 
      success : function(output) {

          var results = output.items[0];
          callback(results); // this is where we call doSomethingWithResult

      }
   });
}
David Hedlund
  • 128,221
  • 31
  • 203
  • 222
  • What if OP, like me, does not like [callback hell](http://callbackhell.com/)? – x13 Nov 20 '15 at 08:42
  • 1
    no i am ok with call back – Vik Nov 20 '15 at 08:46
  • @Vik maybe it will be okay in a small application with only a few of these. – x13 Nov 20 '15 at 08:48
  • 1
    @ThisNameBetterBeAvailable: The article you're linking contains the answers to how to avoid messy callback code. I'm not commenting on styling here. OP had a very specific error, to which callbacks is the solution. Avoiding callback hell is not about not using callbacks, it's about writing them in a non-messy manner. You never want to block the UI thread with a long running operation. – David Hedlund Nov 20 '15 at 08:50
  • @DavidHedlund okay, then i misinterpreted the question. I thought OP wanted to block a non-blocking call. – x13 Nov 20 '15 at 08:52
1

Now I'm no exert at this, but hopefully you'll find something from the code-example that you can use.

I'm binding each row on the .done()-function, which calls another api. I hope this helps.

JS-FIDDLE

(function(){
    //getJSON example
    var jqxhr = $.getJSON( "https://api.myjson.com/bins/2emll", function(data) { 

        for (key in data) {
            $("#list").append("<li class='" + key + "'>" + data[key] + "</li>");
        }

    }).done(function( data ) {

        $("#list li").on("click", function(e){

            var target = e.target.className;

            //ajax example
             $.ajax({ 
                url: 'https://api.myjson.com/bins/309x5',         
                type: 'get',
                data: target,
                dataType: 'json',    
                success: function(data) {
                    var title = $("." + target).text();
                    $("." + target).html(title + '<ul id="ul-' + target + '"></ul>'); 
                }

           }).done(function(data){

                for (key in data) {
                    $("#ul-" + target).append("<li class='" + key + "'>" + data[key] + "</li>");
                }

           });

        });
    });
})();
Salmin Skenderovic
  • 1,750
  • 9
  • 22
  • sorry i am a total beginner. can u write that using my code above? – Vik Nov 20 '15 at 08:47
  • OP asked for blocking a non-blocking asynchronous code execution, not on how to do something when it's done. Also, he wants to pause the code and wait for the result, he probably does not want [callback hell](http://callbackhell.com/). – x13 Nov 20 '15 at 08:47
  • 1
    I've updated my answer and posted a JS-fiddle demo – Salmin Skenderovic Nov 20 '15 at 09:37
0

you can try setting async option to false

like this

function format ( d )     
{  
   var results;
   $.ajax({ 
             url: 'http://127.0.0.1:7101/MUDRESTService/rest/v1/feedbacks/' +   d.FeedbackId + '/child/MudFeedbackDetailsVO?onlyData=true',
             type: 'get',
             dataType: 'json',
             async:false,    
             success: function(output) 
                {
                    console.log(output.items[0].CriticalPath) ; 
                    results =      output.items[0];        
            }
       });
return  results.CriticalPath;
}

NOTE : but it will make your ajax as synchronous and it may be possible that your browser will be unresponsive for the request so there are some points to be noted before using it

By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done() or the deprecated jqXHR.success().

The first letter in Ajax stands for "asynchronous," meaning that the operation occurs in parallel and the order of completion is not guaranteed. The async option to $.ajax() defaults to true, indicating that code execution can continue after the request is made. Setting this option to false (and thus making the call no longer asynchronous) is strongly discouraged, as it can cause the browser to become unresponsive.

fore more information you can read here

Virendra Yadav
  • 652
  • 8
  • 18