The Continuation-Passing Style in JavaScript

The Continuation-Passing Style in JavaScript

ways of cps style implementation

In JavaScript, a callback is a function that is passed as an argument to another function and is invoked with the result when the operation completes. In functional programming, this way of propagating the result is called continuation-passing style (CPS). It simply indicates that a result is propagated by passing it to another function (the callback), instead of directly returning it to the caller.

Synchronous Continuation-Passing Style

Let’s take a look at a simple synchronous function:

function add(a, b) {
  return a + b;

This is the so-called direct style that represents the most common way of returning a result in synchronous programming. The result is directly passed back to the caller using the return instruction. An equivalent continuation-passing style of the preceding function would be:

function add(a, b, callback) {
  callback(a + b);

Now the add() function is a synchronous CPS function, which means that it will return a value only when the callback function completes its execution.

Asynchronous Continuation-Passing Style

Let’s make the preceding function asynchronous:

function addAsync(a, b, callback) {
  setTimeout(function() {
    callback(a + b);
  }, 100);

The setTimeout() is used to simulate an asynchronous invocation of the callback.

Now, let’s try to use this function and see how the order of the operations:

addAsync(1, 2, function(result) {
  console.log('Result: ' + result);

// before
// after
// Result: 3

Since setTimeout() triggers an asynchronous operation, it will not wait anymore for the callback to be executed, but instead, it returns immediately giving the control back to addAsync(), and then back to its caller. The following image shows how this works:

addAsync() operations

When the asynchronous operation completes, the execution is then resumed starting from the callback provided to the asynchronous function that caused the unwinding. The execution will start from the Event Loop, so it will have a fresh stack. Thanks to closures in JavaScript, it is trivial to maintain the context of the caller of the asynchronous function, even if the callback is invoked at a different point in time and from a different location.

Non Continuation-Passing Style Callbacks

There’re several circumstances in which the presence of a callback argument might make you think that a function is asynchronous or is using a continuation-passing style; that’s not always true, let’s take, for instance, the map() method of the Array object:

let result = [1, 2, 7].map(function(element) {
  return element + 1;

The callback is just used to iterate over the elements of the array, and not to pass the result of the operation. The result is returned synchronously using a direct style.

Ads by Google


Frank Lin

Hey, there! This is Frank Lin (@flinhong), one of the 1.41 billion . This 'inDev. Journal' site holds the exploration of my quirky thoughts and random adventures through life. Hope you enjoy reading and perusing my posts.


Practising closures in JavaScript

JavaScript Notes


Practising closures in JavaScript

JavaScript is a very function-oriented language. As we know, functions are first class objects and can be easily assigned to variables, passed as arguments, returned from another function invocation, or stored into data structures. A function can access variable outside of it. But what happens when an outer variable changes? Does a function get the most recent value or the one that existed when the function was created? Also, what happens when a function invoked in another place - does it get access to the outer variables of the new place?

Using Liquid in Jekyll - Live with Demos

Web Notes


Using Liquid in Jekyll - Live with Demos

Liquid is a simple template language that Jekyll uses to process pages for your site. With Liquid you can output complex contents without additional plugins.

Hands on IBM Cloud Functions with CLI



Hands on IBM Cloud Functions with CLI

IBM Cloud CLI allows complete management of the Cloud Functions system. You can use the Cloud Functions CLI plugin-in to manage your code snippets in actions, create triggers, and rules to enable your actions to respond to events, and bundle actions into packages.