Skip to content

Instantly share code, notes, and snippets.

@dphov
Forked from bennadel/external.htm
Created October 11, 2017 08:55
Show Gist options
  • Save dphov/c1b6d10e92b279d34fa17824c7a57f6c to your computer and use it in GitHub Desktop.
Save dphov/c1b6d10e92b279d34fa17824c7a57f6c to your computer and use it in GitHub Desktop.
Exploring Recursive Promises In JavaScript
<!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 &mdash; 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>
<!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 &mdash; 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>
<!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 &mdash; 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>
var promise = [ runTaskA, runTaskB, runTaskC ].reduce(
function( series, task ) {
return( series.then( task ) );
},
Promise.resolve()
);
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