Last active
August 29, 2015 14:19
-
-
Save ThomasBurleson/6681bf595539a98fb5ea to your computer and use it in GitHub Desktop.
Exercise 35: Traditional Nested Async calls before rewritten with Promises or Observables
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
function(window, $, showMovieLists, showError) { | |
var error, | |
configDone, | |
movieLists, | |
queueList, | |
windowLoaded, | |
outputDisplayed, | |
errorHandler = function() { | |
// Otherwise show the error. | |
error = "There was a connectivity error"; | |
// We may be ready to display out | |
tryToDisplayOutput(); | |
}, | |
tryToDisplayOutput = function() { | |
if (outputDisplayed) { | |
return; | |
} | |
if (windowLoaded) { | |
if (configDone && movieLists !== undefined) { | |
if (queueList !== undefined) { | |
movieLists.push(queueList); | |
} | |
outputDisplayed = true; | |
showMovieLists(JSON.stringify(movieLists)); | |
} | |
else if (error) { | |
outputDisplayed = true; | |
showError(error); | |
} | |
} | |
}, | |
windowLoadHandler = function() { | |
windowLoaded = true; | |
// Remember to unsubscribe from events | |
window.removeEventListener("load", windowLoadHandler); | |
// This may be the last task we're waiting on, so try and display output. | |
tryToDisplayOutput(); | |
}; | |
// Register for the load event | |
window.addEventListener("load", windowLoadHandler); | |
// Request the service url prefix for the users AB test | |
$.getJSON( | |
"http://api-global.netflix.com/abTestInformation", | |
{ | |
success: function(abTestInformation) { | |
// Request the member's config information to determine whether their instant | |
// queue should be displayed. | |
$.getJSON( | |
"http://api-global.netflix.com/" + abTestInformation.urlPrefix + "/config", | |
{ | |
success: function(config) { | |
// Parallel retrieval of movie list could've failed, | |
// in which case we don't want to issue this call. | |
if (!error) { | |
// If we're supposed to | |
if (config.showInstantQueue) { | |
$.getJSON( | |
"http://api-global.netflix.com/" + abTestInformation.urlPrefix + "/queue", | |
{ | |
success: function(queueMessage) { | |
queueList = queueMessage.list; | |
configDone = true; | |
tryToDisplayOutput(); | |
}, | |
error: errorHandler | |
}); | |
} | |
else { | |
configDone = true; | |
tryToDisplayOutput(); | |
} | |
} | |
}, | |
error: errorHandler | |
}); | |
// Retrieve the movie list | |
$.getJSON( | |
"http://api-global.netflix.com/" + abTestInformation.urlPrefix + "/movieLists", | |
{ | |
success: function(movieListMessage) { | |
movieLists = movieListMessage.list; | |
tryToDisplayOutput(); | |
}, | |
error: errorHandler | |
}); | |
}, | |
error: errorHandler | |
}); | |
} | |
Since I only want to call this batch of code one (1) time, the Promise solution here is very suitable. For indeterminant streams, then Observables are the way to go...
Now let's try to implement this with ES6 Generators:
Thanks to @rschmukler for his help with these ideas. Just a hint of pending approach
try {
yield netFlix.loadAbInfo();
var [allMovies, config] = yield [netflix.loadMovies(), netflix.loadConfig()];
var output = !config.showInstantQueue ? allMovies.list :
(yield netflix.loadQueue()).map(extractWith(allMovies.list));
tryToDisplayOutput(output);
} catche(e) {
reportError(e);
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The above is truly horrible nesting of parallel and dependent async calls; notice the use of local vars to store data between async calls.
First let's extract our custom NetFlix DataService:
Now we can greatly improve the original code with the use of Promises:
This is declarative-style that is significantly easier to read and maintain.