<!DOCTYPE html>
<html>

<head>
  <script data-require="jquery@*" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
  <script data-require="bootstrap@3.1.1" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
  <link data-require="bootstrap-css@3.1.1" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
  <link rel="stylesheet" href="style.css" />
</head>

<body>
  <div class="container">
    <h1>Using <code>async/await</code>!</h1>
    <div class="row">
      <div class="col-md-12">
        <h3><code>Promise&lt;void&gt;</code></h3>
        <span class="help-block">Using <code>async/await</code> to resolve promise with no return value</span>
        <div class="panel panel-default">
          <div class="panel-body promise-void">
            Waiting...
          </div>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-md-12">
        <h3><code>Promise&lt;{}&gt;</code></h3>
        <span class="help-block">Using <code>async/await</code> to resolve promise that returns an object</span>
        <div class="panel panel-default">
          <div class="panel-body promise-object">
            Waiting for value...
          </div>
          <div class="panel-footer hide">
            
          </div>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-md-12">
        <h3>Handling exceptions</h3>
        <span class="help-block">Promise rejects and exception is thrown</span>
        <div class="panel panel-danger">
          <div class="panel-body promise-reject">
            Waiting to fail...
          </div>
        </div>
      </div>
    </div>
  </div>
  <script src="script.js"></script>
</body>

</html>
type Person = { name: string, age: number };
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const person: Person = {
  name: "George",
  age: 25
};

const voidPromise = (): Promise<void> => new Promise(() => {
    setTimeout(() => {
        let time: Date = new Date();
        let hours: number = time.getHours();
        let greeting: string = hours < 12 ?
            "Good morning" : hours > 12 && hours < 16 ?
                "Good afternoon" : "Good evening";
        let message = `${greeting}, its ${days[time.getDay()]}, ${hours}:${time.getMinutes()}`;
        document.querySelector(".promise-void").innerHTML = message;
    }, 1500);
});

const returningPromise = (): Promise<Person> => new Promise(resolve => {
  setTimeout(() => resolve(person), 2000);
});

const throwingPromise = (): Promise<void> => new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error("This promise will always fail")), 1500);
});

class Promises {
  async whatTimeIsIt(): Promise<void> {
    await voidPromise();
  }
  
  async fetchPerson(): Promise<Person> {
    return await returningPromise();
  }
  
  async failMe(): Promise<void> {
    try {
      await throwingPromise();
    } catch(e) {
      document.querySelector(".promise-reject").innerHTML = (e as Error).message;
    }
  }
}

let promises = new Promises();
promises.whatTimeIsIt();
promises.failMe();

let container = document.querySelector(".promise-object");

/*
// Because not in an async context, I cannot await for fetchPerson, I need to use .then()
promises.fetchPerson()
  .then((result) => {
    container.innerHTML = `${result.name} is ${result.age} years old`;
    
    let panelFooter = document.querySelector(".promise-object ~ div.panel-footer");
    panelFooter.classList.remove("hide");
    panelFooter.innerHTML = JSON.stringify(result);
  });
*/
  
async function showPerson() {
    let result = await promises.fetchPerson();
    container.innerHTML = `${result.name} is ${result.age} years old`;
    
    let panelFooter = document.querySelector(".promise-object ~ div.panel-footer");
    panelFooter.classList.remove("hide");
    panelFooter.innerHTML = JSON.stringify(result);
}
showPerson();
/* Styles go here */

{
  "compilerOptions": {
    "target": "es6",
    "moduleResolution": "node",
    "module": "commonjs"
  }
}