A Solution To Swallowed Exceptions In ES6’s Promises

You have probably heard about ES6’s built-in Promises and how they can provide a way out of JavaScript’s callback hell.

While the intend and purpose for Promises is clear very quickly, getting used to them is not as straightforward and the devil lies in the detail.

One thing that bit us quite late during a recent refactoring and has caused a lot of frustration was the fact that Promises “swallow” exceptions by default.

This does include exceptions such as ReferenceError so that the following code runs perfectly fine, without ever letting you know that something went wrong:

var myPromise = Promise.resolve();
 
myPromise
  .then(function() {
    console.log("Step 1");
  })
  .then(function() {
    console.log("Step 2", thisNameDoesNotExist);
  });

What happens here is that the implementation of Promise wraps our function (the onFulfillment handler as it is called in the language specification) in a try-catch block. Instead of throwing the error and causing our interpreter to crash (but print a convenient error message at least), it catches it and marks the promise p as rejected.

Those of you who have worked with Promises before will say that you need an onRejection handler function of course, and you are perfectly right:

var myPromise = Promise.resolve();
 
myPromise
  .then(function() {
    console.log("Step 1");
  })
  .then(function() {
    console.log("Step 2", thisNameDoesNotExist);
  }, function(e) {
    console.log("Promise rejected, error:", e);
  });

However, this still doesn’t work. What is wrong here? In order to catch errors in the last actual onFulfillment handler in our chain, we need to add another step where nothing but the error catching happens. We could use another .then() with an empty function as its first argument, but a more elegant way is to use .catch() which takes only the onRejection handler for its arguments:

var myPromise = Promise.resolve();
 
myPromise
  .then(function() {
    console.log("Step 1");
  })
  .then(function() {
    console.log("Step 2", thisNameDoesNotExist);
  })
  .catch(function(e) {
    console.log("Promise rejected, error:", e);
  });

Much better, that will do. In theory. In reality though, it is very easy to forget to specify the .catch() handler at the end, have it in the wrong place etc.
Believe me, that will happen, no matter how careful you are. And if it’s not you who forgets it, it will be some guy on your team.

For that reason, Bluebird, one of the most popular Promise libraries, has a “default” onRejection handler which will print all errors from rejected Promises to stderr. This is a huge improvement and while it can still result in unexpected behaviour because it doesn’t interrupt execution, it at least gives a hint where things are dodgy.

While that is all well and good, we didn’t feel like using a library, now that we finally got native support for Promises from io.js. And as it turns out, you don’t have to. Because just as there is process.on(‘unhandledException’, ..), since its 1.4.1 release, io.js also has the unhandledRejection event, which is very similar to Bluebird’s default handler, except that you have to specify it yourself:

var myPromise = Promise.resolve();
 
process.on('unhandledRejection', function(error, promise) {
  console.error("UNHANDLED REJECTION", error.stack);
});
 
myPromise
  .then(function() {
    console.log("Step 1");
  })
  .then(function() {
    console.log("Step 2", thisNameDoesNotExist);
  });

Do this once in your project and you will never have Promises swallow your exceptions again. Happy debugging!

A Tale About Antique Protocols And Not-So-Smart NAT Routers

Digital Signage Remote Control App

Digital Signage Remote Control App

At the land-based branch of our company, we recently discovered the Popcorn Hour S-300, for what we thought could be a solid solution to run promotion videos in of our shops. It is Linux-based and has a very simple client that allows remote control and uploading of videos.

The protocol it uses is antique plain FTP which seemed like a horrible design decision in the first place. But after all, it is quite solid, known to work and this is not exactly an application where security matters, so we didn’t care very much.

Continue reading

Speed up CtrlP vim plugin and automatically clear it’s cache using guard

I just changed from the famous Command-T plugin to CtrlP.

Command-T provides a file navigator for vim, such as the modal that popped up in Textmate when you hit ⌘-t. While it worked well for a while, it relied on an external Ruby library, causing issues with rvm as outlined in my previous post. Then recently it refused to work with MacVim entirely, due to a rendering issue that made it unusable.

While I looked for a way to fix the issue, I stumbled upon CtrlP. CtrlP is a native vim replacement which not only makes it cleaner by design but also a bit faster (and most important for me, it actually worked with my setup).

One issue I never really got around however was the fact that a) building the cache took quite a while, causing quite a delay when you bring it up for the first time and b) the cache wasn’t rebuilt automatically when you changed a file.

I couldn’t really accept this and investigated a bit where it stored it’s cache file. When I found it in $HOME/.cache/ctrlp/$ESCAPED_PROJECT_PATH.txt, I realized that it was full of entries like this:

tmp/cache/sass/9e16d302b803e71649858656bd7da287cac6ab9b/_alternating-rows-and-columns.scssc
tmp/cache/assets/D3B/DD0/sprockets%2Fba7a4ad6548c886b0d4054293aec5e07

As I will never need to open these anyway, I would very much prefer to skip them in the indexing process. CtrlP’s README gave an excellent hint:

set wildignore+=*/tmp/*,*.so,*.swp,*.zip     " MacOSX/Linux
set wildignore+=*\\tmp\\*,*.swp,*.zip,*.exe  " Windows

Restarting vim and trying to bring up CtrlP immediately showed the effect. The startup time was reduced significantly.

This has only solved one of the issues, however. The reloading issue still existed.
Here is what I came up with to solve it, and it may not be the cleanest or best solution. Just for the record, there likely are better ways which involve using vim’s –remote-send option and others. All I was looking for was a quite and dirty solution and here it is:

I immediately thought of guard which I use to automatically run my tests when files change. In order to be able to execute a command only when a file has been added or removed, I cloned guard-shell to make guard-addremove.

To use it to clean your CtrlP cache, make sure that you add guard and guard-addremove to your project’s Gemfile:

gem 'guard'
gem 'guard-addremove'

Now edit your Guardfile so that it has a statement like this in it:

guard 'addremove' do
  # Ignore Vim swap files
  ignore /~$/
  ignore /^(?:.*[\\\/])?\.[^\\\/]+\.sw[p-z]$/
 
  watch(/.*/) { `rm ~/.cache/ctrlp/%Users%pascal%Projects%example.txt &> /dev/null` }
end

You will have to take care to get the path to your cache file right. To do this run vim in your project’s directory, open CtrlP and and check out the contents of $HOME/.cache/ctrlp in another window.

I am aware that this can be improved. Someone who is more experienced with vim than I am might also be able to adjust it so that it can be used with NERDTree and others. I would love to see your examples in the comments.