Promiseとasync/awaitの関係

# これは何？
async/awaitとPromiseの関係を今更だけど自分なりに理解したときのメモです。

# 説明
## Promise
非同期処理の書き方を定めたJavaScriptとしてのルール。

 - うれしい点
  - 非同期処理の書き方が統一され可読性が向上
  - Callbackのネストを浅くすることができる

詳細は[「今更だけどPromise入門」](https://qiita.com/koki_cheese/items/c559da338a3d307c9d88)が分かりやすい。

## async/await
Promiseの弱点である、多い回数のループの処理をより簡単に書くことができるようにするJavaScriptとしてのルール。
Promiseを先に理解する必要があるが覚えるととても便利。

- うれしい点
 - あたかも同期処理のような書き方ができる為、コード量の減少、可読性の向上が期待できる

- 覚書
 - awaitはPromiseの処理完了を待つことができるので、記述的に非同期処理をあたかも同期処理と同じように記述できる
 - awaitを関数の中に入れる場合には、その関数をasyncとして宣言する必要がある
 - Promiseと混ぜて書くことももちろん可能


詳細は[「async/await 入門（JavaScript）」](https://qiita.com/soarflat/items/1a9613e023200bbebcb3)が分かりやすい。

# XHRを書いてみる
fetch()がある現代ではその意味はゼロだけど理解するために書いてみた。

# コード
実行と同時に青い丸を表示します。非同期に`url`で指定したページ(例では「`http://localhost/hoge.html`」)を取得後、`delay` で指定された時間（例では「3秒」）だけ待ち、取得した内容を画面に表示するスクリプトです。

````html
<html>
  <head>
    <title>XHRとasync/await</title>
    <style>
     .blue-circle {
       width: 100px;
       height: 100px;
       background-color:#536DFE;
       border-radius:50%;
     }
    </style>
  </head>
  <body>
    <script>
     function asyncxhr(url) {
         return new Promise( (resolve, reject) => {
             const xhr = new XMLHttpRequest();
             xhr.open('GET', url, true);
             xhr.send();
             xhr.onreadystatechange = function() {
                 if(xhr.status === 200 && xhr.readyState === 4) {
                     setTimeout( () => {
                         resolve(xhr.responseText);
                     }, 3000);
                 /* http status code: https://httpstatuses.com/ */
                 } else if(xhr.status >= 307 && xhr.readyState === 4) {
                     reject(new Error(xhr.statusText));
                 }
             }
             xhr.onerror = function() {
                 reject(new Error(xhr.statusText));
             }
         });
     }

// [ここから] 別の書き方
     async function exec00(url, msec) {
         try {
             const content = await asyncxhr(url, msec);
             console.log('[SUCCESS] ', content);
             let pre = document.createElement('pre');
             pre.innerText = content;
             document.body.append(pre);
         } catch(error) {
             console.log('[ERROR] ', error);
         }
     }

     const url = 'http://localhost/hoge.html';
     const delay = 3000;
     exec00(url, delay);
// [ここまで] 別の書き方

     let div = document.createElement('div');
     div.classList.add('blue-circle');
     document.body.append(div);
    </script>
  </body>
</html>
````

ちなみに`別の書き方`の部分は以下のように即時関数で書くことも可能です。

````javascript
(async function() {
    try {
        const url = 'http://localhost/~kawai/tmp/aaa/index.html';
        const delay = 3000;
        const content = await asyncxhr(url, delay);
        console.log('[SUCCESS] ', content);
        let pre = document.createElement('pre');
        pre.innerText = content;
        document.body.append(pre);

    } catch(error) {
        console.log('[ERROR] ', error);
    }
}());
````


## 実行画面
最低3秒間の時間を待って、取得したページの内容を表示していることが分かる。

<img width="600" alt="Screen Shot 2017-10-29 at 1.42.37 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/61221/a15dd133-18c6-e907-2978-a422a11f821e.png">

# まとめ
Promiseの理解がasync/awaitを使う条件ですが覚えるとコード量が減る上、可読性も上げることができるので全体的にスピードアップが期待できるのではないでしょうか？

# 参照したQiita
- Promise
 - [今更だけどPromise入門](https://qiita.com/koki_cheese/items/c559da338a3d307c9d88)
- async/await
 - [第六章 ～Promiseに潜む闇～（JavaScriptは如何にしてAsync/Awaitを獲得したのか Qiita版）](https://qiita.com/gaogao_9/items/5417d01b4641357900c7#%E7%AC%AC%E5%85%AD%E7%AB%A0-promise%E3%81%AB%E6%BD%9C%E3%82%80%E9%97%87)
 - [async/await 入門（JavaScript）](https://qiita.com/soarflat/items/1a9613e023200bbebcb3)
 - [async await の使い方](https://qiita.com/niusounds/items/37c1f9b021b62194e077)
 - [Javascript Promiseとasync/await](https://qiita.com/okeguch/items/0434f1295226cdd19a53)