0

I am having design issues regarding conditions combined with ajax calls in javascript with the jquery library. Depending on a condition I want to make some ajax-call and then do a procedure - or i do the same procedure without ajax call.

edit 1; to be more concrete with what I wanna achieve:
Depending if some object data already exists I either load it from my local array of objects or otherwise with ajax.

I came up with this structure:

if(x)
{
    $.ajax({
        url:    "interface.php",
        type:    "GET",
        dataType: "json",
        data:{
            my_data : testvalue
        }
    })
    .done(function(data){
        /* PROCEDURE A */
    });
}
else
{   
    // same procedure
    /* PROCEDURE A */
}

I don't like that I have to repeat the exact same code here. I could of course pack the procedure into a function, but that would not change the design.

I would like to have a structure like this:

if(x)
{
    $.ajax({
        url:    "interface.php",
        type:    "GET",
        dataType: "json",
        data:{
            my_data : testvalue
        }
    });
}
/* PROCEDURE A*/

so if x == true do the ajax call first. but do "PROCEDURE A" always. but that's not possible of course because of the asynchronicity of it.

something else that came to my mind is a pseudo-ajax call, but I don't know how this would work out.

thanks for any help and suggestions!

low_rents
  • 4,481
  • 3
  • 27
  • 55
  • 2
    Why not create a procedureA function and call that from the ajax done promise and in the else? There really is no way to get that last example. Unless you do it with your own promises but you will still see the same structure as you do with the if/else – AtheistP3ace Jun 10 '16 at 14:22
  • _"I could of course pack the procedure into a function"_ That's probably cleaner than anything else you're likely to come up with. With the additional benefit that you can wrap the second (`else`) call with [`setTimeout(fn,0)`](http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful) so that it's always called asynchronously so you don't end up with with hard to diagnose issues later. – James Thorpe Jun 10 '16 at 14:24
  • @AtheistP3ace well that's what my first code example already shows. but that's what I don't like design-wise. Like explained in my edit - I want to either load data from a locally stored array (if it exists) or otherwise with ajax. – low_rents Jun 10 '16 at 14:24
  • 3
    So what is the issue with making a function and calling it in the else or done? – epascarello Jun 10 '16 at 14:28
  • 1
    Honestly as much as you don't like the structure it makes sense. If I don't have the data get it and do something else do something. Its clear. You aren't duplicating code. Other people can look at it and know what is going on. You won't be gaining anything by doing it any other way except possibly losing clarity to other people and saving a few bytes. – AtheistP3ace Jun 10 '16 at 14:28
  • @low_rents see this http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – Parvez Rahaman Jun 10 '16 at 14:35
  • In fact, what you want is to run asynchronous code synchronously. It is not possible. – Alex Kudryashev Jun 10 '16 at 15:02
  • @AlexKudryashev no, you got me totally wrong - I just want to avoid unnecessary redundance. – low_rents Jun 10 '16 at 15:08
  • This is not redundancy to call the same function from different places. This is what functions are created. And attempt to call a function synchronously *after* asynchronous code finished is what I've said. – Alex Kudryashev Jun 10 '16 at 15:18
  • 1
    Unnecessary redundance? Calling `procedureA()` from one place or another should not be considered redundant code, more like common practice. – Daniel B Jun 10 '16 at 15:18
  • @DanielB yes, "redundance" was the wrong wording i guess; but see my own anser then you maybe know what i was talking about. – low_rents Jun 10 '16 at 17:09
  • @epascarello I just did not like it this way - you are producing unnecessary branches. think about more functions to be called and more cases. not only true/false but 1, 2, 3, 4, 5, ... instead. you would have to call the function in every case and if you add another function, you need to add the call for it for every case. look at my own answer to see a nice solution I came up with. – low_rents Jun 10 '16 at 17:18
  • @JamesThorpe maybe take a look at my own answer with my deferred object used as pseudo ajax-call. what do you think about it? – low_rents Jun 10 '16 at 17:20
  • You answer is fine, just requires a lot more code than a simple reference to a method. – epascarello Jun 10 '16 at 17:21
  • @epascarello maybe, but imagine multiple cases and multiple procedures. It get's "branchy" and confusing really fast. – low_rents Jun 10 '16 at 17:26
  • Just remember to add your error case. – epascarello Jun 10 '16 at 17:28
  • @epascarello yes, will do that - thanks! – low_rents Jun 10 '16 at 17:30

2 Answers2

0

I found the best answer (at this moment) for myself reading the documentation of jQuery's $.when() (https://api.jquery.com/jQuery.when/) where I stumbled across jQuery's $.Deferred().

Sorry for maybe being unclear asking my question. Maybe my answer makes it better to understand what I did not like about the version with two function calls.

update: thanks to DanielB I simplified the code. instead of creating a deferred object which i resolve and return, i just return $.when(value) now. According to the jQuery docs this is treated like a resolved deferred object - so just what i wanted:

If a single argument is passed to jQuery.when() and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately.

function call(x)
{
    if(x)
    {
        return $.ajax({
            url: "deferred.json", //contains: {"name":"bob"}
            dataType: "json",
            method: "GET"
        });
    }
    else
    {
        // my "pseudo ajax":
        return $.when({"name":"john"});
    }

}

var my_x = true;

// if my_x == true then ajax is called to receive data
// if my_x == false then my deferred object can answer with local data instead
call(my_x)
    .done(function(data){
        procedureA(data);
    })
    .fail(function(){
        alert("error: ajax request failed");
    });

this solution seems more linear and less clumsy to me. Since I simulate an ajax-call with a deferred object I can handle both (or even multiple) cases in exactly the same way. Plus the code doesn't get branched too much.

Community
  • 1
  • 1
low_rents
  • 4,481
  • 3
  • 27
  • 55
  • 1
    There is really no need to create a deferred object. If you want an immediately resolved promise with a value just return `$.when(value)` on it's own. – Daniel B Jun 10 '16 at 21:14
  • @DanielB oh ok, thanks - i was wondering if there is an easier possibility. I'll try that and change my code. – low_rents Jun 10 '16 at 21:17
-1

How about this?

function procA(){
 /*some code here*/
}

if(x)
{
    $.ajax({
        url:    "interface.php",
        type:    "GET",
        dataType: "json",
        data:{
            my_data : testvalue
        }
    })
    .done(function(data){
        procA()
    });
}
else
{   
    // same procedure
    procA()
}
  • 1
    well, yes - but I already mentioned this possibility in my question. – low_rents Jun 10 '16 at 14:26
  • If you are using an if statement with an async call inside the true condition you will need to call the function in the else if you want it to be done under the false condition as well. – Chris Kochel Jun 10 '16 at 14:29
  • According to everyone else commenting, this is the correct solution, why the down vote? – Chris Kochel Jun 10 '16 at 14:40
  • 1
    i did not downvote, but this answer is unnecessary since it's already mentioned in my question – low_rents Jun 10 '16 at 14:58
  • My point is that, your idea of packing the code into a function was the correct course of action. It does not duplicate code, and changing the design with the async nature of this would break it. – Chris Kochel Jun 10 '16 at 15:01