JavaScript Chaining Promises to Promises

October 28, 2014

When you create a Promise you can chain asynchronous behavior by using the then(success,fail) method. The success and fail are callback functions invoked appropriately when the promise is resolved or rejected. Note that since ‘then(…)’ returns a promise, this technique is called promise chaining: p.then(…).then(….).

What I discuss in this post are two subjects
1. How to ‘stitch’ multiple promises together?
2. How to ‘splice’ in an object into a promise chain?
3. How to chain using a promise object as an argument?

What if in a complex application you already have promises objects and want to create promise chains linking these objects to each other? How would you do this with ‘then’ methods? Amazingly, in most examples of using Promises on the web this simple scenario is never presented directly. Granted it doesn’t *seem* to be relevant.

Here is the source of a simple demo based on one of the Dojo Deferred examples. It is ‘normal’ promise chaining. I’m using this as the basis for the investigation presented here. The output displayed on page should be: completed with value: 75

The actual chaining ‘stitching’ is setupTrans().then(function(x){return action()}).then(outputValue);

<!DOCTYPE html>
<html >
<head>

<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"  data-dojo-config="async:false"></script>
	
<script>
require(["dojo/when", "dojo/Deferred", "dojo/dom", "dojo/on", "dojo/domReady!"],function(when, Deferred, dom, on){
	  var balance = 100;

	  function asyncProcess(x){
	    var deferred = new Deferred();
	
	    setTimeout(function(){
	      if(x === 'plus' || x === 'minus'){
	      	 x === 'plus' ? (balance += 25) : (balance -= 25);
	      } 
	      deferred.resolve(balance);
	    }, 1000);
	
	    return deferred.promise;
	  }

	  function setupTrans(){
	  	return asyncProcess('z');
	  }

	  function debitAccount(){
		return asyncProcess('minus');
	  }
	
	  function creditAccount(){
		return asyncProcess('plus');
	  }

	  function outputValue(value){
	    dom.byId("output").innerHTML += "<br/>completed with value: " + value;
	  }
	  
	  on(dom.byId("startButton"), "click", function(){
	  	var debit = true;
	  	var action = debit ? debitAccount : creditAccount;
	  	
	  	setupTrans()
	  	.then(function(x){return action()})
	  	.then(outputValue);
	  	
	  });
});
</script>
</head>
<body class="claro">
    <h1>Output:</h1>
	<div id="output"></div><p />
	<button type="button" id="startButton">Start</button>
</body>
</html>

What is ugly is the inline function. Luckily I found the “Flattening Promise Chains” article where the author shows how to get rid of the function and simplify. However that article didn’t answer my question, how can you simply and directly chain promise objects. What the article showed is that you have to use the correct structure or design. Well, of course, but …


Answer
I thought this would be difficult. The Dojo documentation page never mentions that instead of the first ‘then’ argument being onFulfilled handler function it could be an actual promise object. But this is mentioned in specs such as the Promises/A+ specification. Or does it? The ‘Promise resolution procedure’ seems to mix compile time view with runtime, or I’m reading it incorrectly. Q documentation is very good on this. Will have to research further.

To directly chain separate promise chains the above code sample is modified as follows by just using an existing promise as the argument to another chains then(…) method. However, this can only be done using a promise returning function.

  on(dom.byId("startButton"), "click", function(){
  	var debit = true;
  	var action = debit ? debitAccount : creditAccount;
  	
  	setupTrans()
  	.then(action)
  	.then(outputValue);
  	
  });

Or, to inline the decision:

  on(dom.byId("startButton"), "click", function(){
  	var debit = true;
  	
  	setupTrans()
  	.then(debit ? debitAccount : creditAccount)
  	.then(outputValue);
  	
  });


Chaining using actual promise objects inside the then(f,r) is made easy using the approach shown next, using “scalars”.

Chaining values into promise chains
While looking at this subject I thought about a situation where we want to directly insert a known value into the chain so that the next ‘link’ will use this as the prior handler’s return value.

We have a chain, and I want to put the great Answer in there. This won’t work: var p1 = promiseReturningFunction().then(…).then(’42’).then(….).

Sure you can wrap ’42’ in an inline function then(function(){return ’42’}), but that is yucky. How about a function that does that:

     /** return a function that returns the value */
     function now(value){
    	  return function(){return value;};
      }

Now you can do: var p1 = async().then(…).then(now(’42’)).then(….);

Here is the prior source code with the changes. This is just some of the script changes. The output on screen is:

completed with value: 75
completed with value: Goodbye

      /* ...  */

      function outputValue(value){
        dom.byId("output").innerHTML += "<br/>completed with value: " + value;
      }
      
      function now(value){
    	  return function(){return value;};
      }
      
      on(dom.byId("startButton"), "click", function(){
        var debit = true;
        var action = debit ? debitAccount : creditAccount;
        
        var promise1 = setupTrans()
        .then(debit ? debitAccount : creditAccount)
        .then(outputValue)
        .then(function(){
        	console.log("now do another promise chain...");
        });
        
        promise1.then((now('Goodbye'))).then(outputValue);
        
      });


Using promises objects directly in then(f,r) by using now(x)
With the Promises implementation in Dojo, you can’t use promiseObject.then(anotherPromiseObject). And you can’t use promiseObject.then(when(anotherPromiseObject)). At least, I haven’t figured how to do it.

With the now(x) function shown above, this is easy. The code below will output:

completed with value: 75
completed with value: 100
completed with value: undefined
completed with value: finished both chains

     function now(value){
    	  return function(){return value;};
      }
      
      on(dom.byId("startButton"), "click", function(){
        var debit = true;
        var action = debit ? debitAccount : creditAccount;
        
        var promise1 = setupTrans()
        .then(action)
        .then(outputValue)
        .then(function(){
        	console.log("now do another promise chain...");
        });
        
        debit = false;
        action = debit ? debitAccount : creditAccount;
        var promise2 = setupTrans()
        .then(action)
        .then(outputValue);
        
        promise1
        .then(now(promise2)).then(outputValue)
        .then(now("finished both chains"))
        .then(outputValue);
        
      });
});

Further reading

  1. Original post
  2. Flattening Promise Chains
  3. A Deeper Dive Into JavaScript Promises
  4. How-to Compose Node.js Promises with Q
  5. Promise Anti-patterns
  6. dojo/when
  7. q
  8. General Promise Resources
  9. Promises/A+

Proactive automotive apps?

January 5, 2013

In a previous post, “Synergistic Social Agent Network Cloud” I argued for more proactive apps. I was just reading something that is related to that topic: “Ford Hybrid’s EV+ Feature Learns and Automatically Adjusts Powertrain to Deliver More Electric-Only Driving” Also see “Proactive Agents.”


More robust JUnit tests

November 13, 2012

I created a blog post “Behavior counts for improved JUnit tests” on my other blog.  It shows a possible technique to assure that JUnit tests are robust and are really testing what you think they are testing.


How to interpret User Ratings?

October 28, 2012

I was thinking about those user ratings on products again. I last posted here. Fascinating topic. We all make choices, how?

In one page they mentioned a comic that is so relevant, not only to the subject but also to the Hurricane Sandy, what a coincidence: TornadoGuard

Links

  1. How do you rate user ratings?

The clunkiness of user interfaces

September 18, 2012

So much research and patents on UI design and interaction, yet we still have the most banal GUIs. For example, to share a web page on my Android phone I have to do about twenty operations. We don’t really notice how much we have to do since we are used to it and it becomes ‘natural’ like riding a bike.

In a new blog post I tackled this issue. I think those twenty steps can be easily reduced to two.

Links

Keywords

  • User Experience Design (UXD)
  • Interaction Design (IxD)

New blog

July 7, 2012

Starting to use a new blog at: http://octodecillion.com/

Why? One reason is to start learning a little more technology and have more control of a web site.

Octodecillion?

According to Names of large numbers

Name Short Scale Long Scale
Octodecillion 10^57 10^108

Poverty

June 23, 2012

Poverty

The abandoned wreck lay in the street.

We climbed and jumped; so much to do that week.

A mattress appeared and now our feats grew.

Then one day no more; someone took it away.

Another week, a sewer formed a lake

from which sprung exotic adventures and competitions.

I played a pirate with my wooden sword, my buddy slayed the savage sea beast.

Then one day no more; someone took it away.

Nostalgic, I look back on those days. I was not poor; I enjoyed the endless array

Of things abandoned, trees to climb, hidden corners, and the paradise of neglected yards.

When summer lasted years, and the fun was measured by my socks and

how far they peeked from the holes in the bottoms of my shoes.

On rainy days from the past to today,

I can almost feel my soggy socks

and like an echo in my heart,

hear my mother calling me to come home.

– Josef

Other works

  1. Scattered A short story about the future extremes of …
  2. Hero waits A nano-story.

Follow

Get every new post delivered to your Inbox.