イベントループと非同期


0. Event Loop



  • JavaScriptは単一スレッドプログラミング言語です.つまり、起動時のコールスタックは1つしかありません.

  • ブラウザが提供する非同期関数(settimeout、setInterval、...)Web APIに移動して起動します.起動すると、これらの実行データはコールバックキューに登録されます.callスタックが空の場合、callbackキューのデータはevent loopと呼ばれるcallスタックに入り、実行されます.
  • function test() {
      console.log(1);
      setTimeout(function () {
        console.log(2);
      }, 0)
      console.log(3);
    }
    
    test() // => 1, 3, 2
    //setTimeout이 0초에 실행된다 해도, 콜 스택을 다 비우고 실행되기에 제일 나중에 뜬다.
  • すべての関数が同期して実行されたらどうなりますか?たとえば、settimeoutを3600秒で停止すると、1時間後に関数はアクション(ブロック)を実行できません.
  • 1.非同期処理

  • 非同期関数は、Web APIで動作が完了する順にコールバックキューに入る.この順序を制御したい場合はcallback関数を使用します.
  • 1-1. Callback

  • コールバック関数の意味は以下の通りです.
    パラメータとして関数の関数に入ります.
  • あるイベントによって呼び出された関数(上記の文とは大きく異なる).
  • let printString = (somString, callback) => {
      setTimeout (
        () => {
          console.log(somString)
          callback()
        },
        Math.floor(Math.random() * 100) + 1 //서버와 통신하는데, 임의의 시간이 걸린다고 가정하자.
        )
    }
    
    let printAllString = () => {
      printString("a", () => {
        printString("b", () => {
          printString("c", () => {})
        })
      })
    }
    
    printAllString() // a, b, c (각자 실행되는 시간이 다른데도 순서대로 되어있는 것을 볼 수 있다.)
  • 、すなわち、1つの非同期関数に別の非同期関数をパラメータとして加え、非同期関数が終了すると、パラメータとして入れられた非同期関数を実行(コールバック)する.
  • let callback = (err, data) => {
      if (err) {
        return throw error('something wrong');
      }
      
      return data
    };
  • は、このようにコールバック関数によってエラーを処理することもできる.(プロセスが順調に完了すると、errにnullを追加し、dataに対応するプロセスのデータを追加してコールバック関数を実行する)
  • callbackは、プロセスが増加すると、callback hellと呼ばれる上記の形式で現れる可能性が高いことを示している.このような状況を避けるために現れたのがPromiseです.
  • 1-2. Promise


  • プロセスは非同期操作を実行するオブジェクトです.

  • プロセスには、作成と終了までの3つのステータスがあります.
  • Pending(スタンバイ):非同期操作はまだ完了していません.
  • Fulfilled(履行済み):非同期操作が完了し、結果値が返されます.
  • Rejected(失敗):非同期操作に失敗したか、エラーが発生しました.
  • let promise = () => {
      return new Promise((resolve, reject) => {
      //프로미스 객체는 new Promise로 생성하고 인자로는 executor라는 함수를 인자로 받는다.
      //excutor 함수는 또 resolve와 reject라는 함수를 인자로 받는다.
      
      //만약 서버에서 어떤 데이터를 받아온다고 가정해보자
      데이터를 가져오는 함수(주소, function(데이터) {
       if (데이터) {//데이터 불러오는데 성공했다면
         resolve(데이터);
       }
        reject(new Error); //실패하면
      });
    }
  • promisを生成すると、すぐにexecutor関数が実行されるため、条件分岐を分割してpromisを生成する必要がある.
  • promise()
    .then((data) => {
      //then은 같은 프로미스 객체를 리턴한다.
      //then의 매개변수는 resolve 함수의 인자다.
      return 해당 데이터로 할 다른 작업들()
      //여기서의 리턴은 프로미스 객체를 생성할때의 resolve 안에 들어있는 인자라고 생각해도 될 것 같다.
      //그렇기에 다음 then의 매개변수에 인자로 들어갈 수 있다.
    }
    .then((data2) => {
      //콜백 함수처럼 then을 계속 이어 데이터들을 사용할 수 있다.
      //data2는 위의 리턴된 함수의 결과값이 들어간다.
      //단순히 변수가 리턴되었다면 변수가 then의 인자로 간다.
      return 결과
    }
    .catch((error) => {
        //reject에 인자가 들어갈 경우 catch를 통해 다룰 수 있다.
      console.log(error)
    }
    .finally(() => {
      //finally는 성공했건 실패했건 마지막에 무조건 실행된다.
    })

    Promise.all


  • プロミスをその時までつなぎ続ける方法を見てみましょう.このプロセスでタスクが完了すると、次のthenでのタスクが開始されます.

  • 以前の「タスク」と「then」の「タスク」に関連性がなかった場合、別々に行う必要がありますか?
  • let plusAllData = () => {
      return Promise.all([어떤 데이터1을 가져오는 함수, 어떤 데이터2를 가져오는 함수])
      //당연하게도 위 함수들은 프로미스 객체를 리턴한다.
      //위의 인자로 들어간 함수(프로미스 객체)가 갖는 데이터들을 한꺼번에 갖는 프로미스 객체가 리턴된다.
      .then((allData) => {
        console.log(allData)
      }
    }
    

    1-3. Async & Await

  • ビットのfromisの動作原理と同じですが、その機能はより簡便で同期的です.
  • let AsyncFtn = async () => { //async를 쓰면 함수 자체가 프로미스 객체를 리턴한다.
      let id = await 어떤 아이디를 가져오는 함수() //물론 이 함수들도 프로미스를 리턴하는 함수다.
      let password = await 어떤 비밀번호를 가져오는 함수()
      
      return `${id}의 비밀번호는 ${password}다.` //?!
      //AsyncFtn 함수는 return 값을 갖는 프로미스 객체를 리턴한다.
    }
  • awaitは、この関数が完了した後に実行されるのを待っています.
  • let AsyncFtn = async () => {
      try {
         let id = await 어떤 아이디를 가져오는 함수()
        ...
      } catch (error) {
        console.log(error)
      }
  • try ... catchでエラーを管理できます.
  • 2.終わりの言葉


    ぼやける.自分で、たくさん使ってこそ感じが見つかります.

    役に立つ資料。


    イベントループレッスン
    夢のコードby Ellyのビデオ(3編シリーズ)
    ブログリソース