-
-
Save dphov/c1b6d10e92b279d34fa17824c7a57f6c to your computer and use it in GitHub Desktop.
Exploring Recursive Promises In JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<title> | |
Exploring Recursive Promises In JavaScript | |
</title> | |
</head> | |
<body> | |
<h1> | |
Exploring Recursive Promises In JavaScript | |
</h1> | |
<h2> | |
Recursion With External Function | |
</h2> | |
<p> | |
<em>Look at console — things being logged, yo!</em> | |
</p> | |
<script type="text/javascript" src="../../vendor/core-js/2.4.1/shim.min.js"></script> | |
<script type="text/javascript"> | |
Promise.resolve() | |
.then( | |
function() { | |
console.group( "Recursion - external function." ); | |
return( 3 ); | |
} | |
) | |
.then( | |
function( n ) { | |
// With the recursive function factored out into its own stand-alone | |
// function, it's a lot easier to see that we are creating a totally | |
// TANGENTIAL BRANCH of the Promise chain. | |
// -- | |
// A | |
// | | |
// B --> B'3 --> B'2 --> B'1 --> B'0 | |
// | | |
// C | |
var tangentialPromiseBranch = recurseToZero( n ); | |
return( tangentialPromiseBranch ); | |
} | |
) | |
.then( | |
function() { | |
console.groupEnd(); | |
} | |
) | |
; | |
// I am the recursive function, factored-out into its own function. | |
function recurseToZero( n ) { | |
console.log( "Entering recursive function for [", n, "]." ); | |
// Once we hit zero, bail out of the recursion. The key to recursion is that | |
// it stops at some point, and the callstack can be "rolled" back up. | |
if ( n === 0 ) { | |
return( 0 ); | |
} | |
// Start a NEW PROMISE CHAIN that will become the continuation of the parent | |
// promise chain. This new promise chain now becomes a completely tangential | |
// branch to the parent promise chain. | |
var tangentialPromiseBranch = Promise.resolve().then( | |
function() { | |
return( recurseToZero( n - 1 ) ); // RECURSE! | |
} | |
); | |
return( tangentialPromiseBranch ); | |
} | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<title> | |
Exploring Recursive Promises In JavaScript | |
</title> | |
</head> | |
<body> | |
<h1> | |
Exploring Recursive Promises In JavaScript | |
</h1> | |
<h2> | |
Recursion With Internal Function | |
</h2> | |
<p> | |
<em>Look at console — things being logged, yo!</em> | |
</p> | |
<script type="text/javascript" src="../../vendor/core-js/2.4.1/shim.min.js"></script> | |
<script type="text/javascript"> | |
Promise.resolve() | |
.then( | |
function() { | |
console.group( "Recursion - inline function." ); | |
return( 3 ); | |
} | |
) | |
// In this link of the promise chain, the resolution function is explicitly | |
// named. This way, the function reference can be invoked from within its | |
// own function body. | |
.then( | |
function recursiveFunction( n ) { | |
console.log( "Entering recursive function for [", n, "]." ); | |
// Once we hit zero, bail out of the recursion. The key to recursion | |
// is that it stops at some point, and the callstack can be "rolled" | |
// back up. | |
if ( n === 0 ) { | |
return( 0 ); | |
} | |
// Internally to this promise link, we're going to start a NEW | |
// PROMISE CHAIN whose fulfillment will become the continuation of | |
// the parent promise chain. This fundamentally different from the | |
// reduce() example. | |
var promise = Promise.resolve().then( | |
function() { | |
return( recursiveFunction( n - 1 ) ); // RECURSE! | |
} | |
); | |
return( promise ); | |
// NOTE: To be ultra-concise, I could have written the following; | |
// but, I think that would have made the example harder to follow. | |
// -- | |
// return( Promise.resolve( recursiveFunction( n - 1 ) ) ); | |
} | |
) | |
.then( | |
function() { | |
console.groupEnd(); | |
} | |
) | |
; | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<title> | |
Exploring Recursive Promises In JavaScript | |
</title> | |
</head> | |
<body> | |
<h1> | |
Exploring Recursive Promises In JavaScript | |
</h1> | |
<h2> | |
Using Reduce, Not Recursion | |
</h2> | |
<p> | |
<em>Look at console — things being logged, yo!</em> | |
</p> | |
<script type="text/javascript" src="../../vendor/core-js/2.4.1/shim.min.js"></script> | |
<script type="text/javascript"> | |
var values = [ 1, 2, 3 ]; | |
// Here, we are going to reduce the Values collection down into an asynchronous | |
// SUM calculation in which each link in the Promise chain will add one value to | |
// the running sum and then return the running sum to the next promise link. | |
var promise = values.reduce( | |
function reducer( promiseChain, value ) { | |
// In each iteration of the reducer, we have a PromiseChain that will | |
// resolve with running aggregate (starting with the initial value of 0). | |
// To get at that sum, we have to bind to the resolution of the chain, | |
// thereby adding a new link to the end. | |
var nextLinkInChain = promiseChain.then( | |
function( previousValue ) { | |
return( previousValue + value ); | |
} | |
); | |
// Return the "next link", which is currently the "last link" in the | |
// Promise chain. | |
return( nextLinkInChain ); | |
}, | |
Promise.resolve( 0 ) // Start the promise chain. | |
); | |
// This looks and feels a bit like recursion, but it's not. We're just using an | |
// iterator to translate a series of values into a series of .then() bindings. | |
// But, this could just as easily have been HARD-CODED to look something like: | |
// -- | |
// Promise.resolve( 0 ) | |
// .then( function( sum ) { return( sum + 1 ); } ) | |
// .then( function( sum ) { return( sum + 2 ); } ) | |
// .then( function( sum ) { return( sum + 3 ); } ) | |
// | |
// Read more: // https://github.com/kriskowal/q#sequences | |
// -- | |
// In either case, the reduced Promise will now resolve to the sum of the values: | |
promise.then( | |
function( sum ) { | |
console.log( "Sum of values:", sum ); | |
} | |
); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var promise = [ runTaskA, runTaskB, runTaskC ].reduce( | |
function( series, task ) { | |
return( series.then( task ) ); | |
}, | |
Promise.resolve() | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var promise = Promise.resolve() | |
.then( runTaskA ) | |
.then( runTaskB ) | |
.then( runTaskC ) | |
; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment