Contents tagged with JavaScript

  • But this property is defined as undefined…

    After all these years, JavaScript still occasionally trips me up. Today, I built a test that was failing mysteriously. I use Chai to write my assertions, and that particular test was failing to agree that the array I had constructed was deeply equal to its theoretical value. WebStorm’s test tooling has a diff visualization for deep object or array equality, and this was showing the arrays as equal:Which is it, WebStorm?

  • Snippable: a human-writable multipart document format

    More and more projects are managing their documentation as a bunch of Markdown files in a repository. Sites such as Github make that really easy and convenient, by providing an easy web interface around viewing and editing Markdown files, creating and integrating pull requests, viewing changesets, etc. It seems to provide all the advantages of a wiki, and more, while using a standard and easy set of tools.

  • The sideways stack trace

    Stack trace from a series of asynchronous callsA common pattern in asynchronous programming is the callback pattern. Libraries such as async make use of that pattern to build asynchronous versions of common control flow structures. One unfortunate possible consequence of this is strange stack traces. For instance, here is code that executes five functions serially:

    var functions = [
    function one(done) {done();},
    function two(done) {done();},
    function three(done) {done();},
    function four(done) {done();},
    function five(done) {done();}
    ];

    async.series(functions, function final() {
    debugger;
    });

  • The curse of the never-ending async method call

    Whether you use promises, callbacks, or other abstractions (except maybe the async/await pattern) to deal with asynchrony, control flow is going to get harder to follow. Stack traces are typically meaningless, and finding what went wrong can take substantially more time. One thing that very often goes wrong, especially during development, is when an asynchronous method never calls back. It may be because a service never answers, or because there’s a bug in the code that causes the callback to never be reached. No matter what the cause is, when that happens, you’re typically out of luck because by the time you notice the unusual delay, the execution engine has already left your code without leaving a trace. Breaking into the debugger will just lead you nowhere. You’ll have to tediously re-run and trace the execution of the code with lots of breakpoint into lots of callback functions. No fun.

  • Fluent asynchronous API 6: recursive calls

    This can never work:

    api
    .then(function thenRegisterNextTick(next) {
    process.nextTick(function onTick() {
    api.finally(next);
    });
    })
    .finally(done);

    The “next” callback function gets called from a promise the execution of which depends on the completion of the “then” call. This is a deadlock, albeit a subtle one.

  • Fluent asynchronous API 5: internally calling methods

    One more thing about fluent asynchronous APIs… Because synchronous methods are changed into asynchronous ones by the flasync helper, internal calls of a synchronous method would in principle also have to be asynchronous calls. That would go against the requirements that I’ve set in the first post to provide a way for API authors to write code that is as close as possible to what they would write in a regular API.

  • Fluent asynchronous API 4: Nope, Q won’t work

    As I said at the end of the previous post, I really thought that a promise library, Q in particular, would help, and would enable me to get rid of my helper library. It turns out, after I tried to make it work, that it won’t. The reasons have to do , among other things, with how hard it is to chain a new asynchronous method onto an existing promise, a strange limitation of those libraries. Well, in fact you can very well create a new promise that combines the old one and a new one for the new asynchronous operation, but that would mean managing a list of promises instead of managing the todo list of callbacks I have in my own helper. In other words, I would still have to maintain a helper that would be, maybe, marginally simpler than what I have now, except that it would require a dependency on another much more complex library that I didn’t write.