Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Handling Asynchronous Programming (CPM / Promis...

Handling Asynchronous Programming (CPM / Promises / Events)

Avatar for Jonathan Rodan

Jonathan Rodan

June 20, 2014

Other Decks in Programming

Transcript

  1. Synchronous Code function getQueryResults(parameters) { var query = prepareQueryFromParameters(parameters); return

    downloadBigQueryResult(query); } ! showResultsOnScreen(getQueryResults(xxx));
  2. Continuation Passing Style function getQueryResults(parameters, callback) { var query =

    prepareQueryFromParameters(parameters); var results = downloadBigQueryResult(query, callback); } ! getQueryResults(xxx, showResultsOnScreen);
  3. function getQueryResults(parameters, callback) { var query = prepareQueryFromParameters(parameters); downloadBigQueryResult(query, callback)

    } ! function extractInformationFromBd(parameter, callback) { getQueryResults(parameters, function(result) { //DO WORK callback(processedResult); }); } ! function prepareUiForResult(processedResult, callback) { //Do Work callback(uiElements); } ! extractInformationFromDb(parameters, function(processedResult) { prepareUiForResult(processedResult, showResultsOnScreen); } );
  4. If we add errors function getQueryResults(parameters, callback) { var query

    = prepareQueryFromParameters(parameters); downloadBigQueryResult(query, callback(e, result){ try { if(e){callback(e); return;} callback(null, JSON.parse(result)); } catch (error) { callback(error); } }); } ! getQueryResults(xxx, function(error, results) { if(error){ console.error(err); showErrorMessage(); return; } showResultsOnScreen(results); });
  5. What haven’t we seen in this function? function getQueryResults(parameters, callback)

    { var query = prepareQueryFromParameters(parameters); try { var results = downloadBigQueryResult(query); callback(null, results); } catch (error) { callback(error); } }
  6. What haven’t we seen in this function? function getQueryResults(parameters, callback)

    { var query = prepareQueryFromParameters(parameters); try { var results = downloadBigQueryResult(query); callback(null, results); } catch (error) { callback(error); } } We still don’t know what downloadBigQueryResult does
  7. The real async work happened here function downloadBigQueryResult(query, callback){ var

    loader = makeQueryResultLoader(query); ! loader.addEventListener('load', function(result) { callback(null, result); loader.detachEvents(); }); ! loader.addEventListener('error', function(error) { callback(error); loader.detachEvents(); }); }
  8. The real async work happened here function downloadBigQueryResult(query, callback){ var

    loader = makeQueryResultLoader(query); ! loader.addEventListener('load', function(result) { callback(null, result); loader.detachEvents(); }); ! loader.addEventListener('error', function(error) { callback(error); loader.detachEvents(); }); ! loader.send() }
  9. What does it have in common with this function? function

    getQueryResults(parameters, callback) { var query = prepareQueryFromParameters(parameters); try { var results = downloadBigQueryResult(query); callback(null, results); } catch (error) { callback(error); } }
  10. function getQueryResults(parameters, callback) { var query = prepareQueryFromParameters(parameters); try {

    var results = downloadBigQueryResult(query); callback(null, results); } catch (error) { callback(error); } } No return statement What does it have in common with this function?
  11. What should we return? function asyncFunction(parameters) { //.... return WHAT;

    } ! WHAT.callThisIfReadyOrWhenReady(function(data) { // loaded }).orIfFailedCallThis(function() { // failed });
  12. What should we return? function asyncFunction(parameters) { //.... return WHAT;

    } ! WHAT.callThisIfReadyOrWhenReady(function(data) { // loaded }).orIfFailedCallThis(function() { // failed }); What => Promise
  13. Promise var promise = new Promise(function(resolve, reject) { // do

    a thing, possibly async, then ! if (everythingWorkedFine) { resolve("Stuff worked!"); } else { reject(Error("It broke")); } });
  14. Promise function asyncFunction(parameters) { //.... return new Promise(…); } !

    thePromise.then(function(data) { // loaded }).catch(function(err) { // failed });
  15. Promise function asyncFunction(parameters) { //.... return new Promise(…); } !

    thePromise.then(function(data) { // loaded }).then(function(data) { // loaded - step 2 }).catch(function(err) { // failed });
  16. Promise - States Promises have three possible mutually exclusive states

    • Fulfilled • Rejected • Pending We say that a promise is settled if it is not pending, i.e. if it is either fulfilled or rejected. Being settled is not a state, just a linguistic convenience.
  17. Promises In the then function you can return: • A

    promise or then-able, in which case it will store the promise or then-able for later unwrapping • A non-promise value, in which case it is fulfilled with that value.
  18. Promise var promise = new Promise(function(resolve, reject) { // do

    a thing, possibly async, then ! if (everythingWorkedFine) { resolve("Stuff worked!"); } else { reject(Error("It broke")); } });
  19. Promise function downloadBigQueryResult(query){ return new Promise(function(resolve, reject){ var loader =

    makeQueryResultLoader(query); ! loader.addEventListener('load', function(result) { resolve(result); loader.detachEvents(); }); ! loader.addEventListener('error', function(error) { reject(error); loader.detachEvents(); }); ! loader.send(); }); }
  20. function getQueryResults(parameters, callback) { var query = prepareQueryFromParameters(parameters); downloadBigQueryResult(query, callback)

    } ! function extractInformationFromBd(parameter, callback) { getQueryResults(parameters, function(result) { //DO WORK callback(processedResult); }); } ! function prepareUiForResult(processedResult, callback) { //Do Work callback(uiElements); } ! extractInformationFromDb(parameters, function(processedResult) { prepareUiForResult(processedResult, showResultsOnScreen); } );
  21. A more complex task loadImageList(x) .then(JSON.parse) .then(extractImageUrls) //Return an array

    of urls .then(function(arrayOfImageUrls){ return arrayOfImageUrls //loadImage return a promise of the image .map(loadImage) .reduce(function(previousValue, promiseReturnedFromLoadImage){ return previousValue.then( function() { return promiseReturnedFromLoadImage; }) .then(function(theActualImage){ appendToScreen(image); }); }, Promise.resolve()); }) .then(logAllImagesDisplayed) .catch(logError) .finally(finalize);
  22. Api - constructor resolve(thenable)! • Your promise will be fulfilled/rejected

    with the outcome of thenable resolve(obj)! • Your promise is fulfilled with obj reject(obj)! • Your promise is rejected with obj. For consistency and debugging (eg stack traces), obj should be an instanceof Error. Any errors thrown in the constructor callback will be implicitly passed to reject().
  23. Api - promise promise.then(onFulfilled, onRejected)! • OnFulfilled is called when/if

    "promise" resolves. onRejected is called when/if "promise" rejects. • Both are optional, if either/both are omitted the next onFulfilled/onRejected in the chain is called. • Both callbacks have a single parameter, the fulfillment value or rejection reason. "then" returns a new promise equivalent to the value you return from onFulfilled/onRejected after being passed through Promise.resolve. If an error is thrown in the callback, the returned promise rejects with that error.
  24. Api - promise promise.then(onFulfilled, onRejected)! • "then" returns a new

    promise equivalent to the value you return from onFulfilled/onRejected after being passed through Promise.resolve. If an error is thrown in the callback, the returned promise rejects with that error.