All of the code examples for [Asynchronous Programming: The End of the Loop](https://egghead.io/courses/asynchronous-programming-the-end-of-the-loop).

Learning how to build and manage asynchronous programs is perhaps the most important part of becoming an effective JavaScript programmer. Unlike most programming languages, JavaScript is single-threaded. As a result, JavaScript programs must use async APIs to stay responsive to user input while performing long-running tasks like server requests and animations. You can't get very far in a JavaScript program without running across an asynchronous API. Async programming may seem daunting. How can we write programs that accept user input, run animations, and send server requests over the same period of time? How do we keep the code clear and concise? How do we gracefully propagate and handle asynchronous errors? How can we avoid memory leaks caused by dangling event handlers? JavaScript's loops and try/catch keywords are no help - they only work on synchronous functions. Here's the good news: Asynchronous programming is much easier than it seems. The key is to think differently about events. It is possible to build most asynchronous programs using a handful of simple functions. We will learn why most JavaScript developers approach asynchronous programming the wrong way, and how to avoid these common mistakes. By the end of these lessons you will know the tools, concepts, and libraries required to be an asynchronous programming ninja! In this section, we'll learn the first secret to mastering asynchronous programming: programming without loops. JavaScript's loops can only run synchronously, and cannot be used to repeat asynchronous functions. As a result, in order to master asynchronous programming we must first master programming without loops. In this series we will learn how to program Arrays without loops using just a few simple functions.

<!DOCTYPE html>
<html>
<body>
  
  <script src="lib/script.js"></script>
</body>
</html>
var exchanges = [
  { 
    name: "NYSE",
    stocks: [
      { 
        symbol: "XFX", 
        closes: [
          { date: new Date(2014,11,24), price: 240.10 },
          { date: new Date(2014,11,23), price: 232.08 },
          { date: new Date(2014,11,22), price: 241.09 }
        ]
      },
      { 
        symbol: "TNZ", 
        closes: [
          { date: new Date(2014,11,24), price: 521.24 },
          { date: new Date(2014,11,23), price: 511.00 },
          { date: new Date(2014,11,22), price: 519.29 }     
        ]
      },
    ]
  },
  { 
    name: "TSX",
    stocks: [
      { 
        symbol: "JXJ", 
        closes: [
          { date: new Date(2014,11,24), price: 423.22 },
          { date: new Date(2014,11,23), price: 424.84 },
          { date: new Date(2014,11,22), price: 419.72 }
        ]
      },
      { 
        symbol: "NYN", 
        closes: [
          { date: new Date(2014,11,24), price: 16.82 },
          { date: new Date(2014,11,23), price: 16.12 },
          { date: new Date(2014,11,22), price: 15.77 }
        ]
      },
    ]
  }
];

Array.prototype.concatAll = function() {
  var results = [];
  
  this.forEach(function(subArray) {
    subArray.forEach(function(item) {
      results.push(item);
    });
  });
  
  return results;
};
//[1,2,3].map(function(num) { return num + 1; }) -> [2,3,4]
//[1,2].map(function(num) { return [num + 1, num + 2]; }) -> [[2,3],[3,4]]

var christmasEveCloses =
  exchanges.
    map(function(exchange) {
      return exchange.stocks.
        map(function(stock) {
          return stock.closes.
            filter(function(close) {
              return close.date.getMonth() === 11 &&
                close.date.getDate() === 24;
            }).
            map(function(close) {
              return {
                symbol: stock.symbol,
                price: close.price
              };            
            });
        }).
        concatAll();
    }).
    concatAll();

christmasEveCloses.forEach(function(christmasEveClose) {
  console.log(christmasEveClose);
  // display in plunker preview
  displayInPreview(JSON.stringify(christmasEveClose))
});


// display in plunker preview
function displayInPreview(string) {
  var newDiv = document.createElement("div"); 
  var newContent = document.createTextNode(string); 
  newDiv.appendChild(newContent);
  document.body.appendChild(newDiv)
}