Udemy-React-Course
  • Introduction
  • CodeSandbox で作る開発環境
    • CodeSandbox を使う利点
    • GitHub との連携
    • CodeSandbox の構造
  • 初めての React App
    • 最小限の React アプリケーションの実装
    • JSX と React Element
    • ES2015 のアロー関数について
    • React でアロー関数を使用する
    • 初めての React Component
    • ES2015 の import / export
    • export default
    • 2章の復習
  • State を持ったコンポーネント
    • State とは何か
    • ES2015 の class
    • React Class Component の書き方
    • click された時に setState で state を変更する
    • H20 Component 1
    • H20 Component 2
    • H20 Component 3
    • H20 Component 4
    • map と filter
    • map と filter の実践
  • 実践:TodoApp の作成
    • TodoApp の作成
  • 非同期処理, Promise, Ajax
    • HTTP プロトコルと AJAX
    • 非同期処理と Promise
    • JSON を取得し、その内容をレンダリングする React App の作成
  • 実践:API を叩く App
    • Giphy API を使用して、GIF画像検索する React App の作成
  • Redux の導入
    • Redux の概要
    • createStore で store を作る
    • Provider と Connect / store を React で使用する
    • Redux の全体像の確認
    • Presentational Component と Container Component
    • Action Creator
    • Combine Reducer
  • Redux-thunk を用いた非同期処理
    • Redux-thunk で非同期にアクションを発行する
    • Promise を Redux-thunk 上で活用する
  • React + Redux + Redux を用いた Giphy App
    • store を作る
    • Component に store を connect する
    • Search コンポーネントの作成
    • GiphyAPI を叩くメソッドの作成と Redux-thunk を使った非同期処理
    • 改善
  • 補足資料
    • App = ({name}) => name 型のシンタックス / Destructuring assignment
    • Class Component と Functional Component の使いわけ
  • 参考資料と謝辞
Powered by GitBook
On this page
  • コールバック地獄
  • Promise を使ってコールバックを読みやすく書く
  1. 非同期処理, Promise, Ajax

非同期処理と Promise

JavaScript 一度に一つのことを処理するシングルスレッドという方式なので、基本的に書かれた順に上から実行していきます。しかし一見すると、書かれた順番には実行されていないようにみえる処理があります。それが非同期処理です。

例えば次のコードは、setTimeout を使っているので、console.log は 1000ms 後に実行されます。つまり、ある時間経過したら、何かを実行してね、とあらかじめお願いしておくような処理があるものを、非同期処理といいます。

setTimeout(() => {
  console.log("done", getSeconds());
}, 1000);

こちらもよく見るコードですが、ユーザーのクリックを待ち受けています。 このコードが実行された時には、当然ですがアラートは出ません。ユーザーがクリックするまで待って、された際にはアラートを出してね、という「予約を実行」しているわけです。

import $ from "jquery";

$(".button").on("click", () => {
  alert("click");
});

先ほど書いたコードも非同期処理です。なぜなら「データを取得するのを待って」、 取得できたら HTML を書き換えてね、という予約をしているからです。

const url = "https://developer.mozilla.org/en-US/docs/Web/HTML";

axios.get(url).then(res => {
  console.log(res.data);
  document.body.innerHTML = res.data;
});

ある処理が終わった際に実行される関数のことを「コールバック」といいますが(例えば setTimeout の例では、1000ms 後に実行される console.log() の部分です)、「コールバック」とは「折り返し電話」のことです。我々が非同期処理の際におこなっているのは、このコールバックと同じイメージで、「席が空いたら、連絡をしてね」という予約のお願いをしているわけです。

コールバック地獄

さて、予約のお願いが、一個だけなら話はシンプルですが、予約が連鎖してくると、話は複雑に、そしてコードも複雑になっていきます。

八時になったらピザを頼んで、ピザが来たら田中さんに電話をしてね。そして田中さんがこれるようなら、コーラも改めて注文しておいて。

こんなふうに予約が連鎖してくると、コードはこうなります。

setTimeout(() => {
  console.log("done1");
  setTimeout(() => {
    console.log("done2");
    setTimeout(() => {
      console.log("done3");
      setTimeout(() => {
        console.log("done4");
      }, 1000);
    }, 1000);
  }, 1000);
}, 1000);

コールバックの中で、さらにコールバックを必要をするコードを追加していくと、このように入れ子が深くなってしまいます。これは書くのも、読むのも、メンテナンスするのも大変です。

さて困りました…

Promise を使ってコールバックを読みやすく書く

その解決方法の一つが「Promise」という仕組みを使うことです。

// 現在の時間を取得するための補助的な関数
const getSeconds = () => new Date().getSeconds();

// 非同期処理を Promise を使って読みやすく書く
const async1 = num => {
  // Promise オブジェクトを作ってこれを返す
  // Promise オブジェクトに、コールバックを登録する
  return new Promise((resolve, reject) => {
    // start
    console.log("start" + num, getSeconds());
    // delayed
    setTimeout(() => {
      console.log("done" + num, getSeconds());
      // 処理が終わる場所で、resolve を実行する
      // ここで渡した引数が、then が受け取る引数になる
      // (このコードでは result に入る)
      resolve(num);
    }, 1000);
  });
};

// promise オブジェクトを作って実行する
async1(1)
  .then(result => {
    // resolve がきたら、then に移動する
    // さらに promise オブジェクトを返すことで、
    // 次の then につなげていく
    return async1(result + 1);
  })
  .then(result => {
    return async1(result + 1);
  });

詳しくは、Promise の資料を読んで欲しいのですが、手順をまとめると以下のようになります。

  • 関数を作る。この関数は return new Promise で Promise インスタンスを作ってリターンする。

  • Promise を作る際に、実行したい非同期処理をコールバックとして登録する。

  • 非同期処理が終わる場所で resolve() を実行する。

  • 実行するには、この関数を呼び出して、Promise をインスタンス化する。

  • resolve が実行されると、次の .then() に実行が移動していく。

  • 繋げるためには、次の then の中で、また新たな Promise インスタンスを作成して、リターンしてあげればいい

PreviousHTTP プロトコルと AJAXNextJSON を取得し、その内容をレンダリングする React App の作成

Last updated 7 years ago

https://codesandbox.io/s/yw43kj4rv1