JavaScript – The language without context.

The peanut
You received a peanut.
You do not have the context. There is no way you know why you received a peanut and what to do with it.

If you feel hungry and I have peanuts, you ask me for a peanut, you get a peanut and you eat it.
That is context.

Lets say you want to do other stuff while you wait for a peanut. You want to surf on your phone.
You feel hungry, you say ”I am hungry, can anyone give me a peanut”, and then you start surfing on your phone.
I hear your message and I have peanuts, I give you a peanut. When you receive a peanut, then you eat it.

Now you do not need to know the extended context. It has been reduced to: ”When you receive a peanut, then you eat it.”.
I saw that you reacted this way and found it amusing, so I gave you another peanut, and another…

The Chinese businessmen
A group of Chinese businessmen have traveled to Sweden to look at a secret new prototype that the Chinese company are developing in Sweden. All information is in need to know basis.

The Chinese businessmen have traveled far, they are tired and hungry. Their secret task is to measure the prototype and call a secret buyer and relay the information. If the buyer say OK then the prototype will be shipped to the buyer. The Chinese businessmen are met at the factory by a very polite person.
– I am your personal contact person. I will always be at your side while you are here at the factory. The prototype is in the storage. If you give me instructions what to do with the prototype then I promise to execute them.

The Chinese businessmen really needed the prototype so they said:
– Your instructions are to bring the prototype back here. We will wait.
– Yes, I understand.

The contact person smiled and stood absolutely still.

What can we learn from the peanut and the prototype?
In JavaScript there is no way you can hide your context.
If you try then you end up with a peanut in your hand and a smiling Swede at your site.

The call to Joe, Matilda and Tom
JavaScript aim to remove waiting times everywhere to get a better perceived experience. That is a very noble aim.

The solution to everything in JavaScript is:
– When I am done here, where do you want me to send the result?

Let’s say you put groceries in the checkout and you say to the cashier,
– When you are done processing all the groceries, then call my uncle Joe and he will come and pay.
And then you leave to do other stuff.

Joe get a message to come to the store, he pays and then makes a phone call to aunt Matilda.
– I am done, your turn.

Matilda comes with a bag and put the groceries in the bag, and gives it to little Tom.
Little Tom walk to your home, puts down the bag and press the door bell before he walks away.

In JavaScript this is called callback-hell.

Give me a promise
There are no way of solving this callback hell in JavaScript. You can mask callbacks with promises. You can mask promises with awaits. I call these techniques for oder control.
You could try to mask the promises into iterators and generators, hide them in timer events in the hope that the promise will resolve eventually so you can deliver the result back into your context.

All this is in vain. Whatever you do your context will be lost.
I would like to at least get the possibility to wait for a promise to resolve, without losing my context.

<script>
    'use strict';
    // http://localhost/labs/indexeddb/sync4.php
    function getThingsDoneWithAPromise(ms) {
        console.log('wait() - in wait');
        return new Promise(function(resolve, reject) {
            setTimeout(function(){
                console.log('wait() - waiting done');
                if (Math.random() > 0.5) {
                    resolve('The resulting string');
                } else {
                    reject('Something went wrong');
                }
            }, ms);
        });
    }
    console.log('This console message represent my context (call stack) before the promise');
    var $myPromise = getThingsDoneWithAPromise(10);
    
    // Suggested alternative #1
    var $response = $myPromise.then( function($resolve) { return $resolve; }, function($reject) { return $reject; } );
    
    // Suggested alternative #2
    var $response = waitForPromise($myPromise);
    
    console.log($response); // Log should show: "The resulting string" or “Something went wrong
    console.log('This console message represent my context after the promise');
</script>

With waitForPromise() you will not burst your stomach with peanuts, you are able to keep your job at the factory and you can buy your food without activating all of your family. Last but not least – Life become less complicated for JavaScript programmers.

2017-04-13 I must update my own article. Check this out:

<script>

    /*
    Simulates calling an async function without losing the context.
    Result is that answers can come at any time and they are matched with the right context.
    Tested on Opera 43.0, Firefox 52.0.2
     */

    console.clear();

    function cmd($inNumber) {

        var $context = {
            'original_number': $inNumber,
            'new_number': 0
        };

        function callback($number) {
            $context.new_number = $number;
            var $row = 'orig: ' + $context.original_number + ', new: ' + $context.new_number;
            // console.dir($context);
            console.log($row);
        }

        myFunc($inNumber, callback);

    }

    function myFunc($number, $func) {
        var $answer, $timeout;
        $answer = $number / 3;
        $timeout = Math.floor((Math.random() * 10000) + 100);
        setTimeout(function() {
            $func($answer);
        }, $timeout)
    }

    var $i;
    for ($i = 100; $i > 0; $i--) {
        cmd($i);
    }

</script>

 

CharZam