Posts

Showing posts with the label promises

Trees of Promises in ES6

This blog post shows how to handle trees of ES6 Promises , via an example where the contents of a directory are listed asynchronously. The challenge We’d like to implement a Promise-based asynchronous function listFile(dir) whose result is an Array with the paths of the files in the directory dir . As an example, consider the following invocation: listFiles('/tmp/dir') .then(files => { console.log(files.join('\n')); }); One possible output is: /tmp/dir/bar.txt /tmp/dir/foo.txt /tmp/dir/subdir/baz.txt The solution For our solution, we create Promise-based versions of the two Node.js functions fs.readdir() and fs.stat() : readdirAsync(dirpath) : Promise<Array<string>> statAsync(filepath) : Promise<Stats> We do so via the library function denodify : import denodeify from 'denodeify'; import {readdir,stat} from 'fs'; const readdirAsync = denodeify(readdir); const statAsync = d...

Tracking unhandled rejected Promises

In Promise-based asynchronous code, rejections are used for error handling. One risk is that rejections may get lost, leading to silent failures. For example: function main() { asyncFunc() .then(···) .then(() => console.log('Done!')); } If asyncFunc() rejects the Promise it returns then that rejection will never be handled anywhere. Let’s look at how you can track unhandled rejections in browsers and in Node.js. Unhandled rejections in browsers Some browsers (only Chrome at the moment) report unhandled rejections. unhandledrejection Before a rejection is reported, an event is dispatched that you can listen to: window.addEventListener('unhandledrejection', event => ···); The event is an instance of PromiseRejectionEvent whose two most important properties are: promise : the Promise that was rejected reason : the value with which the Promise was rejected The following example demonstrates how this event works: window.addEven...

Promise-based functions should not throw exceptions

This blog post gives tips for error handling in asynchronous, Promise-based functions. Operational errors vs. programmer errors In programs, there are two kinds of errors: Operational errors happen when a correct program encounters an exceptional situation that requires deviating from the “normal” algorithm. For example, a storage device may run out of memory while the program is writing data to it. This kind of error is expected. Programmer errors happen when code does something wrong. For example, a function may require a parameter to be a string, but receives a number. This kind of error is unexpected. Operational errors: don’t mix rejections and exceptions For operational errors, each function should support exactly one way of signaling errors. For Promise-based functions that means not mixing rejections and exceptions, which is the same as saying that they shouldn’t throw exceptions. Programmer errors: fail quickly For programmer errors, it usually makes sense to fail as quickly...

ES proposal: async functions

Async functions are an ECMAScript proposal by Brian Terlson. It is at stage 3 (candidate). Before I can explain async functions, I need to explain how Promises and generators can be combined to perform asynchronous operations via synchronous-looking code. Writing async code via Promises and generators For functions that compute their one-off results asynchronously, Promises, which are part of ES6, are becoming increasingly popular. One example is the client-side fetch API , which is an alternative to XMLHttpRequest for retrieving files. Using it looks as follows: function fetchJson(url) { return fetch(url) .then(request => request.text()) .then(text => { return JSON.parse(text); }) .catch(error => { console.log(`ERROR: ${error.stack}`); }); } fetchJson('http://example.com/some_file.json') .then(obj => console.log(obj)); co is a library that uses Promises and generators to enable...

ECMAScript 6 promises (2/2): the API

Image
This blog post is outdated. Please read chapter “ Promises for asynchronous programming ” in “Exploring ES6”. This blog post is an introduction to asynchronous programming via promises in general and the ECMAScript 6 (ES6) promise API in particular. It is second in a series of two posts – part one explains foundations of asynchronous programming (which you may need to learn in order to fully understand this post). Given that the ECMAScript 6 promise API is easy to polyfill for ECMAScript 5, I’m mainly using function expressions and not ECMAScript 6 arrow functions , even though the latter are much less verbose. Promises Promises are a pattern that helps with one particular kind of asynchronous programming: functions (or methods) that return their results asynchronously. To implement such a function, you return a promise , an object that is a placeholder for the result. The caller of the function registers callbacks with the promise to be notified once the result has been computed. Th...

ECMAScript 6 promises (1/2): foundations

Image
This blog post is outdated. Please read chapter “ Asynchronous programming (background) ” in “Exploring ES6”. This blog post explains foundations of asynchronous programming in JavaScript. It is first in a series of two posts and prepares you for part two , which covers promises and the ECMAScript 6 promise API. The JavaScript call stack When a function f calls a function g , g needs to know where to return to (inside f ) after it is done. This information is usually managed with a stack, the call stack . Let’s look at an example. function h(z) { // Print stack trace console.log(new Error().stack); // (A) } function g(y) { h(y + 1); // (B) } function f(x) { g(x + 1); // (C) } f(3); // (D) return; // (E) Initially, when the program above is started, the call stack is empty. After the function call f(3) in line (D), the stack has one entry: Location in global scope After the function call g(x + 1) in line (C), the stack...