Steve
Steve

Reputation: 5952

Get callback info back to original calling function

Let's say you have a Javascript function that calls a web service method. So that webservice completes and calls a callback function, which has the result.

How do I get that result back into the original function that called the web service method? Essentially, I'm trying to "synchronize" an asynchronous call.

Update:

This is what I'm trying to do. I'm validating based on the return value of a web service.

$.validator.addMethod("zzz",
    function(value, element) {

        // Call web service function using ASP.NET Ajax.
        // Get callback value to determine validity.

        return this.optional(element) || ***return t/f based on validity***;
    },
    function(value, element) { return msg; }
);

so I guess I could do this instead:

$.validator.addMethod("zzz",
    function(value, element) {

         $.ajax({
              async: false
              url: **** web service url ****
              success: set t/f to validity var
         });

        return this.optional(element) || ***return t/f based on validity var***;
    },
    function(value, element) { return msg; }
);

Upvotes: 0

Views: 820

Answers (6)

coolnalu
coolnalu

Reputation: 355

The only way I can think of is like

function b(){
    var a = null;
    $.get("abc.json", {
        success: function(data){
            a = data;
        }
    });
    while(a == null){}
    alert(a);
}
b();

But generally this isn't good and may cause the browser to complain a script is taking too long to finish.

Upvotes: 0

Romain Hippeau
Romain Hippeau

Reputation: 24375

You should not do that. Just carry on with your processing from the point of the callback. You risk hanging the browser completely if the call does not return.

If you control the server side then you could write some code on the js side to aggregate calls and then write something on the server side to unpack and do multiple calls from each nested call in the aggregate. When the responses come back then aggregate those and send them back. This will save on performance since large calls are cheaper than many small calls.

We did that on a project I worked on and it worked very nicely. It also consolidates logic on the js side to not be spread all over due to all the async callbacks.

Upvotes: 1

Nick Craver
Nick Craver

Reputation: 630439

Since you're using jQuery, you can use async:false in your ajax command, like this:

$.ajax({
  //options..
  async: false
});
//this code will run after the request returns

Note though, this blocks the UI (locks up the browser), it's better to continue the work that depends on the result in the success callback, like this:

$.ajax({
  //options..
  success: function(data) {
    doSomethingWithResult(data);
  }
});

Upvotes: 2

Ben Zotto
Ben Zotto

Reputation: 71018

Not to be trite, but you can't create synchronousness from asynchronousness, only the other way around. You need to design your code to allow for this, which generally means callbacks all the way through your call chain.

There is one idiosyncratic exception, which is that you can specify 'false' on the raw XMLHttpRequest's 'open' method's async parameter, which will cause the send method to block until it's done. But this is likely not compatible with some frameworks and is pretty inflexible. Most JS stuff is async.

Upvotes: 1

treznik
treznik

Reputation: 8124

Well what you're trying to accomplish is simulating a sleep command, so your script "waits" for your ajax request? But that doesn't really makes sense. That's why you have to callback in the first place, to continue with the flow once the request has returned a reply, since you cannot predict its response time.

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1074495

Essentially, you can't, but you can break up that function into "before" and "after" parts, like so:

function foo(a) {
    var b, c;

    // == The "before" part:

    b = /* ... */;

    // == Call the service:

    callWebService(a, b, callback);

    // == The "after" part is contained within the callback:

    function callback(d) {
        // Do something with a, b, c, and d
    }
}

But it's important to note that foo will return before callback is called. There's no way to prevent that with an asynchronous call, so if you're looking to have the function return something, you'll have to refactor (or use a synchronous call, but that's a very bad idea). The refactoring would involve whatever's calling foo to provide a callback and expect the result to be provided that way rather than as a return value.

Upvotes: 1

Related Questions