looking for a full-immersion/face-to-face HTML5, JavaScript, and Mobile Web Development training in the heart of London? Book your spot

Thursday, September 03, 2015

On Cancelable Promises

Update
The awesome Lie function got improved and became an official module (yet 30 lines of code thought). Its name is Dodgy, and it's tested and even more awesome!
If every developer talks about similar issues with Promises, maybe we should just drop our "religion" for an instant and meditate about it ...

Not today though, today is just fine

We've been demanding from JS and Web standards to give us lower level APIs and "cut the crap", but we can do even more than that: simply solve our own problems whenever we need, and "cut our own crap" by ourselves and for our own profit, instead of keep moaning without an outcome.
Today, after reading yet another rant about what's missing in current Promise specification, I've decided to write a very simple gist:


After so many discussions and bikeshead about this topic, I believe above gist simply packs in its simplicity all good and eventually bad intents from any voice of the chorus I've heard so far:
  1. if we are in charge of creating the Promise, we are the only one that could possibly make it abortable and only if we want to, it's an opt in rather than a default or a "boring to write" subclass
  2. it's widely agreed that cancellation should be rather synonymous of a rejection, there's no forever pending issue there, just a plain simple rejection
  3. one of the Promise strength is its private scope callback, which is inevitably the only place where defining abortability would make sense. Take a request, a timer, an event handler defined inside that callback, where else would you provide the ability to explicitly abort and cleanup the behavior if not there?
  4. being the callback the best pace to resolve, reject, and optionally to abort, that's also the very same place we want to be sure that if there was a reason to abort we can pass it along the rejection, so that we could simply ignore it in our optionally abort aware Promises, and yet drop out from any other in the chain whenever the rejection occurs or it's simply ignored
  5. the moment we make the promise malleable from the outer world through a p.abort() ability, is also the very same moment we could just decide to resolve, or fully fail the promise via p.resolve(value) or p.reject(error)
As example, and shown in the gist itself, this is how we could opt in:
var p = new Lie(function (resolve, reject, onAbort) {
  var timeout = setTimeout(resolve, 1000, 'OK');
  // invoking onAbort will explicit our intent to opt-in
  onAbort(function () {
    clearTimeout(timeout);
    return 'aborted'; // will be used as rejected error
                      // it could even be undefined
                      // so it's easier to distinguish
                      // between real errors and aborts
  });
});
After that, we can p.abort() or try other resolve or reject options with that p instance and track it's faith:
p.then(
  console.log.bind(console),
  console.warn.bind(console)
).catch(
  console.error.bind(console)
);
Cool, uh? We have full control as developers who created that promise, and we can rule it as much as we like when it's needed ... evil-laugh-meme-here

Cooperative code

In case you are wondering what's the main reason I've called it Lie in the first place, it's not because a rejected Promise can be considered a lie, simply because its behavior is not actually the one defined by default per each Promise.
Fair enough for the name I hope, the problem might appear when we'd like to ensure our special abortable, resolvable, rejectable own Promise, shouldn't be passed around as such. Here the infinite amount of logic needed in order to solve this problem once for all:
var toTheOuterWorld = p.then(
  function (data) {return data},
  function (error) {return error}
);
// or even ...
var toTheOuterWorld = Promise.resolve(p);
That's absolutely it, really! The moment we'd like to pass our special Promise around and we don't want any other code to be able to mess with our abortability, we can simply pass a chained Promise, 'cause that's what every Promise is about: how cool is that?
// abortable promise
var cancelable = new Lie(function (r, e, a) {
  var t = setTimeout(r, 5000, 'all good');
  a(function () { clearTimeout(t); });
});

// testing purpose, will it resolve or not?
setTimeout(cancelable.reject, 1000, 'nope');
// and what if we abort before?
setTimeout(cancelable.abort, 750);



// generic promise, let's log what happens
var derived = cancelable.then(
  function (result) { console.log('resolved', result); },
  function (error)  { error ?
    console.warn('rejected', error) :
    console.log('ignoring the .abort() call');
  }
).catch(
  function (error)  { console.error('cought', error); }
);

// being just a Promise, no method will be exposed
console.log(
  derived.resolve,
  derived.reject,
  derived.abort
);

Moaaar lies

If your hands are so dirty that you're trying to solve abort-ability down the chain, don't worry, I've got you covered!
Lie.more = function more(lie) {
  function wrap(previous) {
    return function () {
      var l = previous.apply(lie, arguments);
      l.resolve = lie.resolve;  // optional bonus
      l.reject = lie.reject;    // optional bonus
      l.abort = lie.abort;
      return Lie.more(l);
    };
  }
  if (lie.abort) {
    lie.then = wrap(lie.then);
    lie.catch = wrap(lie.catch);
  }
  return lie;
};
We can now chain any lie we want and abort them at any point in time, how cool is that?
var chainedLie = new Lie(function (res, rej, onAbort) {
  var t = setTimeout(res, 1000, 'OK');
  onAbort(function (why) {
    clearTimeout(t);
    return why;
  });
})
.then(
  console.log.bind(console),
  console.warn.bind(console)
)
.catch(
  console.error.bind(console)
);

// check this out
chainedLie.abort('because');
Good, if you need anything else you know where to find me ;-)
How to opt out from lies again?
var justPromise = Promise.resolve(chainedLie);
OK then, we've really solved our day, isn't it?!

As Summary

Promises are by definition the returned or failed value from the future, and there's no room for any abort or manually resolved or rejected operation in there.
... and suddenly we remind ourselves we use software to solve our problems, not to create more, so if we can actually move on with this issue that doesn't really block anyone from creating the very same simple logic I've put in place in about 20 well indented standard lines, plus extra optional 16 for the chainable thingy ... so what are we complaining about or why do even call ourselves developers if we get stuck for such little effort?
Let's fell and be free and pick wisely our own footgun once we've understood how bad it could be, and let's try to never let some standard block our daily job: we are all hackers, after all, aren't we?

Saturday, August 22, 2015

The Dumb Side Of Technology

How many times you told a machine "how stupid" it was? How much technology are you surrounding with these days? This is a quick rant about few situations I've found myself involved: enjoy!

The one with the light sensor

This is the most hilarious story I could tell these days. I've found an office (it's just a room in a renewed building) that's so sophisticated and full of sensors, that I have nothing to do when I get into the room. The conditioner and the lights switch on thanks to a sensor!
"so what's the problem?" you ask? I have a projector and there's no bloody sensor switch so I can't see anything because as soon as I move the light goes on again. More over, the sensor activates also the conditioner, and what about the window? ... well, there is one, but I cannot open it.
They'll never come back with a solution, I'll probably change office because not being in control of keeping lights switched off in your own, freaking expensive office, is very frustrating!
This is also how the conversation with office management went:
  • me: I need to keep the light off
  • they: Sir, we have highly automated office and a green policy, we have sensors for lights
  • me: I have said, I need to keep the light switched off
  • they: why would you need that Sir?
  • me: I have a projector, I can't see a thing with such bright illumination
  • they: I see, we'll ask about it and let you know how much will it cost. Meanwhile, have you tried shutting down the blinds?
  • me: .... walk away astonished ...

The 7GB free SD card that Android will not use to update

I have finally received the Lollipop 5.1 update for my Motorola E, a very Essential device that might be enough for 80% of people out there. The Motorola E first generation has its own storage of 2.something GB. Android fits together with all its pointless apps I don't use (pointless because mandatory) and it says it needs at least 850MB to be installed. I check the storage, there are 300MB left plus more than 7GB on the SD card. The SD card is mounted in recovery mode, so it's perfectly usable as alternative storage to execute a System update. No way, I had to remove a couple of apps because it is not possible to move Apps to SD card, only few awesome apps can do that, and I wonder why on earth this is not a requirement in order to be accepted in the Android store.
Why are these app so obtrusive that need to be installed in the equivalent of the Linux /boot, /etc, and /system folder? Why on earth there is an SD card if for an update I'll have same problems iPhone C had a while ago? At least iPhone C does not even accept an SD card. How dumb is being unable to use free space? What is that free space useful for? Why are all these Google apps I don't use incapable of being moved to the SD card?
These and many more questions that will never be answered in the next episode of: How dumb is the free space management in every Phone OS!

Not just updates

If you have your app in your SD card you are free to move that card in your new shiny phone and keep the precious data with you if you are still in the same OS, or a newer version of such OS. There is no reason your app needs to be in the main storage and I hope these will all change their requirements, beside modern phones have more than 2GB of main storage, the point is a completely different one.

The slower automatic checkout

Have you ever found at some supermarket an automatic checkout that won't scan the next item until it has said entirely the price of the previously scanned one? I did, and I've imagined myself staring in front of the working person telling me the price loudly of everything I've bought. What the actual heck were they thinking when they released the software for that machine?

The classic airport double lifts paradox

The book I've started and never completed is entitled: 20 Floors of JavaScript. Its title is inspired by the fact it's the 20th anniversary of JavaScript, and also its aim is to discover how to program multiple Array of lifts/elevators.
I've realized in 37 years of life that lifts are the most stupidly programmed software you can imagine, and there are tons of solutions that could be implemented but apparently the software is the same that somebody wrote in 1978 or similar years.
Just to name one utterly idiotic situation with lifts, try to take one at the airport, in a place where there are at least two lifts.
One will be inevitably full, and while its doors are closing, somebody will press the button in order to call the other lift.
The drama begins.
The lift that was going upstairs will interrupt its closing doors procedure, opening them back, and waiting other 5 seconds before eventually closing them again. While doors are closing again, the second impatient person will press the button again.
People will start shouting "DON'T PRESS THE BUTTON" and some fight might have already picked up in the queue or someone got angry with the person that is pressing the button, calling him/her idiot.
Truth is, the only idiot, and the elephant in the room nobody wants to see because it not a real entity, is the lift and its software. Not only these lift have a weight sensor, so that eventually these could ignore changing floor if the weight is too high, these lift also have a camera. Having a camera means that when the weight is 0, the lift can take a screenshot of its internal. When the weight is not zero and doors are closing, the lift can take another screenshot of its internal and compare that image, pixel per pixel, with the initial empty one, and unless every person of the lift managed to dress like a part of that lift interiors and in camera prospective, the lift could easily tell if its full enough to ignore any extra request to re-open the door and let somebody else get in. This is not too sophisticated at all, this is just basic common sense applied. Moreover, every extra button push could simply be counted as unsigned short which, if more than 2, should ignore the request. This will avoid deadlocks when people for the third time see doors closing, and somebody from the outside call the lift again. This would surely be over-engineered in any single lift situation, but it can actually speed up the logic when there are at least 2.
This, and many other little tricks I've no idea why whoever is programming lifts software is not thinking about. They are more like dumb, passive, queues, incapable of optimizing a single operation.

Rant over, share your funny story if you like!

Thursday, August 20, 2015

TinyCDN: a portable blazing fast CDN

In this blog post I am introducing tinyCDN, a middle-ware module and a standalone static file server that does much more than others, and it has been designed from the scratch to work on most constrained, Internet of Things, environments, as well as production server.

Saturday, August 15, 2015

The line between Events and Promises

In this post I will talk about Events and Promise limits, trying to fill all gaps with a 498 bytes sized library called notify-js.

Saturday, August 08, 2015

Bringing SSL To Your Private Network

In this entry I will describe and provide how to run a HTTPS server in your home network, in order to test new HTML5 APIs.

Friday, July 31, 2015

ArchLinux UEFI and Dell XPS 2015

unrelated important thing first: I am blogging on my own website too, you can read my very first public entry in there!
I will keep posting here less web-centric related issues, or mostly rants, and will post there interesting stuff about HTML5, JavaScript, client/server and Mobile Web development ... now, back to the topic ...

archibold and my Dell XPS Developer Edition

So they changed my motherboard today, it suddenly stopped recognizing the Hard Drive, and even trying other drives didn't work at all.
Kudos to Dell for their assistance: the day after a person with already all necessary pieces arrived at my door and substituted the Motherboard with a very quiet and professional attitude.
... when I've asked assistance for a Lenovo Yoga Pro 3 they never even come back ...

If you've never heard about archibold, it's an installer which aim is to simplify ArchLinux and, optionally, GNOME configuration. Since I already backed up my Dell, and even if it was working like a charm, I've decided to erase it and see if I could make it work via UEFI.
Apparently this BIOS could be quite problematic and while efibootmgr seems to work without problems, it actually doesn't: it puts the EFI label into the list of Legacy boot-able devices so it won't work!

Not only the boot manager

If you have tried my installer before, I suggested to use UEFI=NO and enable Legacy mode on the bios. This was because not only I couldn't figure out how to install via UEFI, but I was using genfstab generated /etc/fstab during the installation and it was storing wrong UUIDs.

Finally Managed to install with UEFI boot!

The TL;DR story is that if you have an EFI partition created through gparted, and you have Syslinux on it, you should go in the part of the bios where you can add UEFI partitions manually, selecting syslinux/syslinux.efi file to boot from.

I know this sucks, but it's something you eventually do "once in a lifetime" so I believe it's OK.
Another setting change I made was the following one: disable secure boot and be sure legacy is off.