3

I know it sounds like something that's been asked before, but for all my hunting, I can't find anything matching what I'm looking for.

I'm working on a project that's rather heavily based on Ajax. I'm using jQuery, but even with its beautifully streamlined code, it's still messy when I've got it to the point that the code is exactly the same, except for one single command passed through the data field.

So I tried setting it up inside a handler function, like so:

function _call(task, opts, async) {
    if(typeof async !== "boolean") { async = true; }
    opts = $.extend({}, opts, options);
    $.ajax({
        url: "myphpfile.php",
        dataType:"JSON",
        type:"POST",
        async:async,
        data: { task: task, opts: opts }
    }).done(function(data) { return data; });
}

For those who read through, you'll notice that there's a var, options, that hasn't been defined in the example. It has actually been assigned, it's just been omitted for clarity purposes.

I came to realize that this doesn't work, as even when it's set to async: false, the code still continues after the call of _call(...), therefore not getting the results in time. I've tried a few different variations, including passing an anonymous function to the handler and then using that as the .done() function, but it wouldn't interact with outside variables, defeating the purpose.

All I'm looking for is a system that will let me use it something like this:

var returnedData = _call("thisismytask");
var returnedDataWithOptions = _call("thisisanothertask", {'option': 'option1'});

I really hope this is possible. I'm sure it would be, as the main purpose of functions is to remove the need for unnecessarily repeated code.

Thanks. :)

Slavo
  • 15,255
  • 11
  • 47
  • 60
Connor Deckers
  • 2,447
  • 4
  • 26
  • 45

5 Answers5

5

You could do this:

function _call(task, opts) {
    opts = $.extend({}, opts, options);
    return $.ajax({
        url: "myphpfile.php",
        dataType:"JSON",
        type:"POST",
        data: { task: task, opts: opts }
    });
}

It removes the need for passing a callback into _call, but functions just the same.

_call("thisisanothertask", {'option': 'option1'}).then(function(data) {
  // function body here
});
Andy
  • 61,948
  • 13
  • 68
  • 95
1

you are probably best doing this

function _call(task, opts, callback) {
    opts = $.extend({}, opts, options);

    $.ajax({
        url: "myphpfile.php",
        dataType:"JSON",
        type:"POST",
        data: { task: task, opts: opts }
    }).done(function(data) { callback(data); });
}

use like this

_call("thisisanothertask", {'option': 'option1'}, function(data) {
   //do things with data
});

You cant really do this, as _call cant return straight away as it may take a while to get a response and even if you could it could lock your browser which is not good.

var returnedData = _call("thisismytask");
var returnedDataWithOptions = _call("thisisanothertask", {'option': 'option1'});

you need to use it like this:

_call("thisismytask", null, function(returnedData) {
   //use returnData
});

_call("thisisanothertask", {'option': 'option1'}, function(returnedDataWithOptions) {
  //use returnedDataWithOptions
});

If you needed the result of thisismytask before thisisanothertask you would have to do:

_call("thisismytask", null, function(returnedData) {

   _call("thisisanothertask", {'option': 'option1'}, function(returnedDataWithOptions) {
     //use returnData

     //use returnedDataWithOptions
   });

});
chrisarton
  • 4,401
  • 2
  • 18
  • 15
1

You should be using callbacks. You also shouldn't be using async: false as this will block the UI thread in browser. You can use jQuery.when() to sync your various tasks. First change your method like this:

function _call(task, opts) {
    opts = $.extend({}, opts, options);
    return $.ajax({
        url: "myphpfile.php",
        dataType:"JSON",
        type:"POST",
        data: { task: task, opts: opts }
    });
}

Now you can call it like this:

$.when(
    _call("thisismytask"),
    _call("thisisanothertask", {'option': 'option1'})
).done(function(firstCallResults, secondCallResults) {
    //*CallResults is an array with the following structure: [data, statusText, jqXHR]
    var returnedData = firstCallResults[0];
    var returnedDataWithOptions = secondCallResults[0];
    ...
});

This way you keep all the benefits of AJAX asynchrounous nature (those tasks will run in parallel unless server doesn't support it) and get your results back together when they are all available.

tpeczek
  • 23,867
  • 3
  • 74
  • 77
0

I found a solution. @Slavo pointed it out to me.

https://stackoverflow.com/a/6685294/563460
As you're making a synchronous request, that should be

function getRemote() {
     return $.ajax({
         type: "GET",
         url: remote_url,
         async: false,
     }).responseText; }

Example - http://api.jquery.com/jQuery.ajax/#example-3

Now I just have to decode from text to proper JSON. Thank you everyone. :)

Community
  • 1
  • 1
Connor Deckers
  • 2,447
  • 4
  • 26
  • 45
  • this is not a useful solution. Please learn proper async programming methods. – Alnitak Sep 11 '13 at 15:58
  • As the original question was "Performing a synchronous Ajax request from jQuery?" - this answer is the best solution. Sure, async ajax calls have their benefits and are much thread safer, but the question was not, "Is an async ajax call better than a sync call?" - This solution is synchronous and returns the responseText, after it is recieved. Can be empty if the server responds eg a 404 Not found with empty body. Some additional global hooks via $.ajaxSetup could be helpful. Eg errorCode callback or error and complete. – Scriptlabs Aug 18 '14 at 16:34
0

Use jQuery's syntax - its worked for me,

$.ajaxSetup({async: false});
Dadaso Zanzane
  • 6,039
  • 1
  • 25
  • 25