Tuesday, 8 September 2020

Promise Inspection Part 2

In my previous post I said that probably there was an easier way than inheritance to implement synchronous inspection in Promises, so that's what this post is about.

This mechanism is used differently from the one shown last week. Rather than receiving an executor function and creating a Promise from it, we receive an existing Promise, and chain to her a new Promise that is expanded with the expected inspection methods (isFulfilled(), isRejected(), getValue(), getReason()). The code is pretty straight forward. The new Promise waits for the original Promise and when this one is completed or rejected it sets her inpection properties accordingly.

An interesting point is that indeed the new Promise does not hold the isFullfilled, value, reason... values (used by the corresponding isFullfilled(), getValue()... expansion methods) as data fields (that hence could be set from outside), but as variables that get trapped by the closures used for each of those expansion methods. This is an old trick used for creating private fields in JavaScript.

Donc, voilà le code:

 

//returns a new Promise expanded with inspection methods
function enableSyncInspect(pr){
    //we trap these variables in the closure making them sort of private, and allow public access only through the inspection methods that we add to the new promise
    let isFulfilled = false;
    let value = null; //resolution result
    
    let isRejected = false;
    let reason = null; //rejection reason
    
    let isPending = true;

    //create a new promise that gets resolved-rejected by the original promise and gets expanded with inspection methods
    let prWrapper = pr.then(_value => {
        isPending = false;
        isFulfilled = true;
        value = _value;
        return _value;
    }, _reason => {
        isPending = false;
        isRejected = true;
        reason = _reason;
        return _reason;
    });

    prWrapper.isFulfilled = () => {
        return isFulfilled;
    }

    prWrapper.getValue = () => {
        return isFulfilled 
            ? value
            : (() => {throw new Error("Unfulfilled Promise");})(); //emulate "throw expressions"
    }

    prWrapper.isRejected = () => {
        return isRejected;
    }

    prWrapper.getReason = () => {
        return isRejected
            ? reason
            : (() => {throw new Error("Unrejected Promise");})(); //emulate "throw expressions"
    }

    prWrapper.isPending = () => {
        return isPending;
    }

    return prWrapper;
}


That we can use like this:

 

function formatAsync(msg){
    return new Promise((resFn, rejFn) => {
        console.log("starting format");
        setTimeout(() => {
            console.log("finishing format");
            resFn(`[[${msg}]]`);
        }, 2000);
    });
}

function printValueIfFulfilled(pr){
    if (pr.isFulfilled()){
        console.log("Promise resolved to: " + pr.getValue());
    }
    else{
        console.log("Promise NOT resolved yet");
    }
}

//async main
(async () => {
    let pr1 = formatAsync("Bonjour");
    let syncInspectPr = enableSyncInspect(pr1);

    console.log("isPending: " + syncInspectPr.isPending());

    //this fn runs in 1 seconds (while the async fn takes 3 seconds) so it won't be fulfilled at that point)
    setTimeout(() => printValueIfFulfilled(syncInspectPr), 1000);

    let result = await syncInspectPr;
    console.log("result value: " + result);
    
    printValueIfFulfilled(syncInspectPr);

})();

//Output:
// starting format
// isPending: true
// Promise NOT resolved yet
// finishing format
// result value: [[Bonjour]]
// Promise resolved to: [[Bonjour]]


As usual I've uploaded it into a gist.

Tuesday, 1 September 2020

Promise Inheritance and Synchronous Inspection

The other day, taking a look into the advanced Promises provided by bluebirdjs I though about how to implement a very small and basic part of the funcionality, the Synchronous Inspection, that basically stores the value resolved by a Promise and allows accessing to it synchronously (read the doc for a real explanation). There are other ways to implement it, but I decided to use inheritance, and has been interesting enough to post it here.

In a previous post I already made use of Promise inheritance, but I did not need to take into account the resolve and reject callbacks passed to the executor function received by the constructor. In this case I wanted to override those resolve-reject callbacks, so that I would add my additional logic (setting the isFulfilled and value or isRejected and reason values) and then invoke the originals (the parent ones let's say) so that they perform their magic logic of invoking the continuations (the "then"-"catch" handlers). These callbacks are not exposed as methods in the Promise class (one could think of having implemented them as protected methods in another language...), so in order to get hold of them to use them, we create an internal Promise with an executor function that just will give us a reference to those original callbacks, and then we call the original executor function passing to it resolve-reject callbacks that perform our extra logic and then invoke the originals. Our "then" overriden method invokes the internal Promise parent method, so that all the logic performed by the Promise class to set the continuations is run.

The explanation above is really confusing, so you better just check the code of my SyncInspectPromise class:

 


class SyncInspectPromise extends Promise{
    constructor(executorFn){
        //compiler forces me to do a super call
        super(() => {});

        this._isFulfilled = false;
        this._value = null; //resolution result
        
        this._isRejected = false;
        this._reason = null; //rejection reason
        
        this._isPending = true;
        
        //we need to be able to invoke the original resFn, rejFn functions after performing our additional logic
        let origResFn, origRejFn;
        this.internalPr = new Promise((resFn, rejFn) => {
            origResFn = resFn;
            origRejFn = rejFn;
        });

        let overriddenResFn = (value) => {
            this._isPending = false;
            this._isFulfilled = true;
            this._value = value;
            origResFn(value);
        };

        let overriddenRejFn = (reason) => {
            this._isPending = false;
            this._isRejected = true;
            this._reason = reason;
            origRejFn(reason);
        };

        executorFn(overriddenResFn, overriddenRejFn);
    }

    isFulfilled(){
        return this._isFulfilled;
    }

    getValue(){
        return this.isFulfilled() 
            ? this._value
            : (() => {throw new Error("Unfulfilled Promise");})(); //emulate "throw expressions"
    }


    isRejected(){
        return this._isRejected;
    }

    getReason(){
        return this.isRejected()
            ? this._reason
            : (() => {throw new Error("Unrejected Promise");})(); //emulate "throw expressions"
    }

    isPending(){
        return this._isPending;
    }

    then(fn){
        //we set the continuation to the internal Promise, so that invoking the original res function
        //will invoke the continuation
        return this.internalPr.then(fn);
    }

    catch(fn){
        //we set the continuation to the internal Promise, so that invoking the original rej function
        //will invoke the continuation
        return this.internalPr.catch(fn);
    }

    finally(fn){
        return this.internalPr.finally(fn);
    }
}


And we can use it like this:

 

function sleep(ms){
    let resolveFn;
    let pr = new Promise(res => resolveFn = res);
    setTimeout(() => resolveFn(), ms);
    return pr;
}

function printValueIfFulfilled(pr){
    if (pr.isFulfilled()){
        console.log("Promise resolved to: " + pr.getValue());
    }
    else{
        console.log("Promise NOT resolved yet");
    }
}

(async () => {
    let pr1 = new SyncInspectPromise(res => {
        console.log("starting query");
        setTimeout(() => {
            console.log("finishing query");
            res("hi");
        }, 3000);
    });
    console.log("isPending: " + pr1.isPending());

    //this fn runs in 1 seconds (while the async fn takes 3 seconds) so it won't be fulfilled at that point)
    setTimeout(() => printValueIfFulfilled(pr1), 1000);

    let result = await pr1;
    console.log("result value: " + result);
    
    printValueIfFulfilled(pr1);

})();

//output:
// starting query
// isPending: true
// Promise NOT resolved yet
// finishing query
// result value: hi
// Promise resolved to: hi

As usual I've uploaded it into a gist.

Sunday, 23 August 2020

Method Composition

Every now and then I'll find something that will remind me again of how beautiful a language JavaScript is. This time I came up with a not much frequent need, Method Composition. Function Composition is quite popular, and libraries like lodash-fp with its Auto-Curried, iteratee-first, data-last approach make composition really powerful.

In this case I'm talking about composing methods. May seem a bit odd, but I came up with a case where it could be rather useful. I have several methods that modify (yes, in spite of the immutability trend I continue to use mutable objects on many occasions) the object on which they are invoked, and I'm calling several of them in a row, to the point where it would be useful to add a new method to the class that just performs all those consecutive calls. Adding a new method to the "class" is so easy as adding the new function to the prototype of the "class" (if I just wanted to add it to an specific instance I would add it to the instance __proto__ (or instance [[Prototype]])). In order to invoke the sequence of methods we have to bear in mind that each method can have a different number of parameters, but Function.length comes to our rescue.

It's more useful to just see the code than further explaining it, so here it goes the factory function that composes the different methods:

 

function composeMethods(...methods){
    //use a normal function, not an arrow, as we need "dynamic this"
    return function(...args) {
        methods.forEach(method => {
            let methodArgs = args.splice(0, method.length);
            method.call(this, ...methodArgs);
        })
    }
}

And given a class like this:

 

class Particle{
    constructor(x, y, opacity){
        this.x = x || 0;
        this.y = y || 0;
        this.opacity = 1;
    }

    move(x, y){
        this.x += x;
        this.y += y;
    }

    fade(v){
        this.opacity += v;
    }
}

We'll use it this way to compose the "move" and "fade" methods into a new "moveAndFade" method:

 

//composing "move" and "fade" and adding it as a new "moveAndFade" method
Particle.prototype.moveAndFade = composeMethods(Particle.prototype.move, Particle.prototype.fade);

let p1 = new Particle();
console.log(JSON.stringify(p1));

//x, y, v
p1.moveAndFade(4, 8, -0.1);
console.log(JSON.stringify(p1));

p1.moveAndFade(2, 3, -0.2);
console.log(JSON.stringify(p1));

// {"x":0,"y":0,"opacity":1}
// {"x":4,"y":8,"opacity":0.9}
// {"x":6,"y":11,"opacity":0.7}


I've uploaded it into a gist.

Saturday, 22 August 2020

Fix Broken Folder

I'll share this experience here in case it can help anyone. This morning I was copying a bunch of films on Ubuntu from my laptop to and external NTFS disk. The copying got stuck at 50% and after a while I cancelled it. The usb disk seemed to be still in use but anyway I disconnected it (as so many times before). When connecting it again it looked fine, save for the folder "Films" on which I was copying the files. Opening the folder from the UI it showed up empty. From the command line I could do a cd into it, but doing a ls would return reading directory '.': Input/output error

I did not enter into panic as all the other folders with important stuff (and already backed up in other disks) like personal pictures, documents... seemed intact, so I was only losing like 400 films... (many of them scattered over other old, smaller, external disks). Anyway, managing to recover the folder would be nice...

The first thing I found about was running the badblocks command to verify that the disk was physically OK (I honestly thought so, as all the other folders looked good I was more leaning to think of a file system error). badblocks was taking so long, so I did a fast search and found that it could take up to 70 hours!!! and just to verify something, not to fix the disk...

I read by passing something that I already knew but was missing, that even if NTFS disks are perfectly supported in Linux since a very long while... it's Microsoft who has the full knowledge of the system, so I thought I could check if Windows was able to recognize the folder.

Rebooting my laptop on Windows and trying to navigate the folder I got this error:
The File or Directory is Corrupted and Unreadable

A fast search brought up this article, that recommended doing a chkdsk /f on the problematic disk.

After a few seconds the first messages stating that some error had been found and had been fixed showed up, so it was quite reassuring. After less than 10 minutes (for a 2TBs disk with a 30% use disk), the procedure was finished and the contents of my "Films" folder were back again! I'm putting below some of the fix messages that chkdsk returned:

Saturday, 8 August 2020

Reconcile the French People

There's much talking (but no acting at all) in France about the Islamisation, communitarism-separatism (immigrant communities rejecting to integrate and assimilate, and creating their own close, xenophobic and medieval communities), the skyrocketing levels of criminality and violence (now we call it "ensauvagement"), the ridiculous laxity of the justice system (particularly when the criminals are part of a so called "minority")... and bla, bla, bla...

Regarding this separatism, there's a nice and well thought (as usual, it's interesting how much someone like me that has swung to the center-right continues to respect these "traditional left" guys) set of writings/drawings in Charlie Hebdo issue 1461, 600 jours pour rabibocher les Francais/600 days to reconcile the French people. From all of them, there's one by Riss that particularly stands out, so I'm translating it here (sorry for my lack of translation skills):

Travelling educates the young people

Young people between 15 and 25 years old having committed repeated criminal acts will be comdemned to spend the prison sentence expected for adults by the Penal Code, not in prison, but in a foreign country, in a French NGO. 10 months of prison will become 10 months to be spent in New Delhi taking care of people infected with leper or tuberculosis. 12 months of prison will become 12 months in a Health center in a slum in Haiti. The aim is to move these young people away from their environmnet and to make them discover new horizons. At the end of their condemnation purged this way, they'll get a job offering in France, related to the activities conducted in the NGO that has taken them in and educated them.

As I have little trust in some humans I'm not sure to what extend this could work, but for sure it's a better option than the ridiculous prison sentences in a comfortable French prison and the social aids that the tax payers will pay them once they are out committing crimes again... The other options that I would favor: removing their French nationality if they are bi-nationals, penal labour or plain-good-old capital punishment... I guess are not acceptable by our naive European societies...

 

 

Sunday, 2 August 2020

Retry Async Function

The other day I had an async function that could fail (rejecting its promise) quite often and wanted to retry it a few times if needed. In the end I wanted to generate a new function with the retry functionality in it. I had done this in the past with pure promises and had been a bit more complex (it was something along the lines of what you can find here), but with async-await the code is so simple that I'm not sure why I'm posting it here, anyway:

 

//wrap setTimeout with an async-await friendly function
function sleep(ms){
    console.log("sleep starts");
    let resolveFn;
    let pr = new Promise(res => resolveFn = res);
    setTimeout(() => {
        console.log("sleep ends");
        resolveFn();
    }, ms);
    return pr;
}

//fn: function returning a Promise
//if the Promise is rejected we'll retry up to "attempts" times, with a "timeout" in between
//returns a new function with retry logic
function addRetryToAsyncFn(fn, attempts, timeout){
    return async (...args) => {
        while (attempts--){
            try{
                return await fn(...args);
            }
            catch(ex){
                console.log("attempt failed");
                if (!attempts)
                    throw ex;
            }
            await sleep(timeout);
        }
    };
}

//given an async function: getAndFormatNextTicket
//we'll use it like this:
let formattedTicket = await addRetryToAsyncFn(getAndFormatNextTicket, 5, 1000)("Francois");

Thanks to async/await the retry code for an async function is basically the same as the one for a normal function:

 

function addRetry(fn, attempts){
    return (...args) => {
        while (attempts--){
            try{
                return fn(...args);
            }
            catch(ex){
                console.log("attempt failed");
                if (!attempts)
                    throw ex;
            }
        }
    };
}

You can see a full example here.

Saturday, 1 August 2020

Tour In Nova, Bordeaux

Last week I did a day-trip to Bordeaux (the so beautiful "La belle-endormie"). As the train approached Saint Jean (the gorgeous main train station nicelly refurnished a few years ago) I could see in the distance a new addition to the city's skyline, the Tour In Nova. Bordeaux is a low rise city, with whole neighbourhoods made up by 1 - 2 stories buildings (though not as low rise as Toulouse, probably the lowest-rise mid-size city in the world). This listing about Bordeaux buildings seems quite accurate to me. As you can see it got 3 (unappealing I can say) administrative towers in the 70's, peaking at 90 meters, and then some residential towers that I assume are mainly in Grand Ensembles.

However, in the last years some new, interesting "towers" (in France anything above 40 meters is a tower) and modern neighborhoods have been-are being built. La Cité du Vin is a prominent example. This building is located in the new Bassins a Flot area, where you'll find tons of 8-9 stories residential (and some office) buildings with interesting shapes, roofs and facades.

The other most notorious development area is the Euratlantique district, close to the main train station. I've seen this area emerge over the last years and I was feeling a bit disappointed so far, but the Tour In Nova has been a great surprise. Though not reaching 60 meters in height it's well visible when you enter the city, and the upper block looks really, really nice to me. It reminds me of the BEC tower in Bilbao (that is higher, but not that beautiful). It's a real shame that the crazy French security laws concerning high-rise buildings, that force you to keep a dedicated security team in place in buildings higher than 60 meters (well, it's a simplification, but you get the idea) prevented it from getting some additional floors (with 5-6 extra floors to reach 75-80 meters it would certainly stand out quite more). Anyway, if it had not been that law it would have been some "rednecks against modernity" citizens group who would have fight against such a "skyscraper"...

I can not close this post without mentioning the main reason for my last trip to Bordeaux, Les Bassins de Lumières. Some French people still have amazing ideas, living up to the glorious cultural traditions of the country. To leverage an enormous submarine base created by Fascist Italy and Nazi Germany during the occupation, to create a massive Digital art center (that opened just one month ago) is for sure one of those amazing ideas. Bordeaux is well worth a several days visit, and this new cultural space is well worth an afternoon.