Callback関数ない非同期コード作成方法

<h1>Callback関数ない非同期コード作成方法</h1>
非同期処理をどうすればうまく処理できるかという観点から、その前chapterで取り上げたPromiseというメカニズムです。<br>
Promiseが定着し、Promise以降にasyncawaitという非同期関数を利用して、<br>
内部的なメカニズムはコールバックのように動作する非同期コードであるにもかかわらず、コード上では完全な同期コードのように作成できる文法体系です。

<h2>tsconfig.json修正</h2>
tsconfig.jsonにlibを追加すると、async、awaitを使用できるようになります。

```typescript:tsconfig.json
      "lib": [
        "ES2016", 
        "dom"
      ],
```

<h2>async 使用方法</h2>
request というメソッドを非同期関数に変えるために asyncを付けます。
そしてasyncはPromiseオブジェクトをリターンするため、Promiseを付ける必要があります。
<br><br>
fetchは非同期処理をしますが、同期コードのように使用できます。非同期処理をするfetchの前にawaitというoperateを付けます。まるでfetchがreturnするように見えます！ 
<br><br>
実際には既存のpromiseベースとして同じように作用します。
リターンする値もpromiseなのでawaitをリターンしてあげなければなりません。

```typescript:asyncとpromiseケース
    /**
     * async CASE
     * async awitを使ってコールバックのない非同期関数を作成
     * awaitを使う為には、その関数も非同期である必要があり、関数にasyncを宣言する。
     * @param callback async関数はpromiseをreturnする
     */
     async request<AjaxResponse>(): Promise<AjaxResponse> {
      const response = await fetch(this.url);
      return await response.json() as AjaxResponse;
    }


    /**
     * Promise CASE
     * @param callback callback関数をパラメータとして受け取って、returnとして返す
     */
     getRequestWithPromise<AjaxResponse>(callback: (data: AjaxResponse) => void): void {
      // fecth(A,B)  A - URL, B - options(default : GET method)
      // return promoise object - resolve
      // catch - reject
      // fetch return promise object

      // returnされるpromiseオブジェクトがresolve(sucess)であれば、then()メソッドが実行され
      // リターンなるpromiseオブジェクトがreject(fail)ラーメンcatch
      fetch(this.url) 
        // xhrはJSON.parseを使用したが、短所が同期的に作動するということ。
        // jsonデータがとても大きくなったらuiが止まる問題点が存在する。
        // thenにて非同期処理にする。
        .then(response => response.json()) 
        .then(callback) 
        .catch(() => {
          console.log(" no data ");
        })
    }

```
<br>
非同期関数を呼び出す関数も非同期関数でなければなりません。
そのためにasyncを付けて、リターンをPromiseに囲む必要があります。
<br>

```typescript:async関数の呼び出し元
  async getData(): Promise<NewsFeed[]> {
    return this.request<NewsFeed[]>();
  }

  getDataWithPromise(callback: (data: NewsFeed[]) => void): void {
    return this.getRequestWithPromise<NewsFeed[]>(callback);
  }
```
<br>


getDataは内部で非同期処理をするロジックがあるため、await operatorをつけます！
awaitをつけたため、render関数にはasyncをつける必要があります。
また、リターンがvoidですが、async関数のため、Promiseにて囲む必要があります。
```typescript:async関数の呼び出し元
    render = async (id: string): Promise<void> => {
        const api = new NewsDetailApi(CONTENT_URL.replace('@id', id));
        // asyncを呼出
        const { title, content, comments } = await api.getData();

        this.store.makeRead(Number(id));
        this.setTemplateData('comments', this.makeComment(comments));
        this.setTemplateData('currentPage', this.store.currentPage.toString());
        this.setTemplateData('title', title);
        this.setTemplateData('content', content);

        this.updateView();
    }

    render = (id: string): void => {
      const api = new NewsDetailApi(CONTENT_URL.replace('@id', id));
      // function(callbackA)
      // callbackA - callbackfunction(parameter) {}
      //
      api.getDataWithPromise((data: NewsDetail) => {
        const { title, content, comments } = data;

        this.store.makeRead(Number(id));
        this.setTemplateData('comments', this.makeComment(comments));
        this.setTemplateData('currentPage', this.store.currentPage.toString());
        this.setTemplateData('title', title);
        this.setTemplateData('content', content);

        this.updateView();
      })
    }
```