1

The normal synchronous way of doing things is nice and straightforward.

  • A function takes in inputs.
  • The function performs an action with those inputs.
  • The function ejects out a value (returns a value).
  • The value that is ejected can be stored into a variable, used directly in other parts of the synchronous code, etc.

But async doesn't seem to be able to do this.

Let's say that I have a service that I want to sell. The price of the service varies by location.

I have a user:

  • Enter in a Zip Code
  • Zip Code gets sent to an API while returns a city name.
  • I use the city name to run a super huge function that returns a price.
  • I then want to use the price in other parts of my synchronous code, and that synchronous code is super long and spans across numerous functions that all depend on the price value.

Code:

var calcPrice = function(city){
    // stuff runs
    return price;
};

// Async Function, taken from http://www.zippopotam.us/
// The "place name" is the city.

var returnLocationInfoByZip = function(zip, callback){
    var client = new XMLHttpRequest();
    var response;
    client.open("GET", "http://api.zippopotam.us/us/" + zip, true);
    client.onreadystatechange = function() {
        if(client.readyState == 4) {
            response = client.responseText;
            callback(JSON.parse(response));
        };
    };
    client.send();
};

var zip = "94043";

var price = returnLocationInfoByZip(zip, function(response){
   calcPrice(response.places[0]["place name"]);
});

// This does not work. I'm going to call this the "dependent processing" part of my code.

functionThatDependsOnPrice(price);
AnotherFunctionThatDependsOnPrice(price);
MoreFunctionsThatDependsOnPrice(price);
EvenMoreFunctionsThatDependOnPrice(price);

// This I THINK would work instead

returnLocationInfoByZip(zip, function(response){
   price = calcPrice( response.places[0]["place name"] );
   functionThatDependsOnPrice(price);
   AnotherFunctionThatDependsOnPrice(price);
   MoreFunctionsThatDependsOnPrice(price);
   EvenMoreFunctionsThatDependOnPrice(price);
});

Stuffing all of that code in the callback is really really ugly and confusing.

I would like to just use the price variable inside of my normal synchronous code. But the value from calcPrice never gets returned and thus never gets stored into the price variable. The value of calcPrice is forever stuck inside the asynchronous branch of my code flow which forces me to do all my other dependent processing inside the asynchronous branch / callback.

So a few questions:

  • Is it correct that asynchronous code is never able to return a value back into the synchronous code? The normal synchronous way of doing and thinking about things just won't work.

  • Is a fat callback pretty much normal?

I could go the Promise route, but if I do that I'm just stuffing all of the dependent processing into my then function... it's a little cleaner looking but it's still nested deep inside other things.

fuzzybabybunny
  • 5,146
  • 6
  • 32
  • 58

1 Answers1

1

Is it correct that asynchronous code is never able to return a value back into the synchronous code?

Yes, pretty much. It does depend on the enviroment though. For example: in the browser a file depency library like requirejs depends on asynchronous flow. In NodeJS however, they abstracted it so that you can fetch dependencies synchronous style (like you would with Import in Java).

If you need to fetch a resource from another webservice or database you will likely always need a callback. This is because of the asynchronous nature of the javascript engine. The script execution will not halt whenever it requests resources from the underlying enviroment (for example the browser). As such you can execute multiple asynchronous requests simultaneously.

Is a fat callback pretty much normal?

It depends on your preference and code style. If it's readable and maintainable, why shouldn't you have a fat callback? Many would argue that is not clean though. Personally, I'd prefer a more flat architecture by implementing something like Promises.

Hless
  • 3,326
  • 20
  • 22
  • Thanks for the answer! Yeah, I think Promises is the lesser of the two evils. On a side note, have you encountered any major issues with Promises not being supported on browsers? The official MDN docs on Promises has a big disclaimer that it's experimental tech. – fuzzybabybunny Oct 28 '14 at 12:41
  • There are various promises libraries that do not rely on experimental browser features. A few notorious ones being: **Q** (https://github.com/kriskowal/q) and **jQuery Deferred** (http://api.jquery.com/category/deferred-object/). Also, I failed to mention that `XMLHTTPRequest` does actually have a parameter that makes the request synchronous, but then again this could cause you all sorts of other troubles if a request times out. – Hless Oct 28 '14 at 12:48
  • Haha, they are notorious? So stay away from them? – fuzzybabybunny Oct 28 '14 at 12:48
  • I meant popular ^^, English isn't my mother tongue. Lots of documentation on those two, and if you use the jQuery one, it's pretty much baked into the AJAX wrapper. – Hless Oct 28 '14 at 12:51