[TIL]200921 Asynchronous & Promise-1


2つの文字列をパラメータとして使用して、共通文字を順番に返す関数を作成します.(スペースと重複文字は含まれません)
commonCharacters('acexivou', 'aegihobu'); //결과 : 'aeiou'
複文で説明できると思いますが、複文の勉強が足りないせいか、繰り返し複文を使っています
比較したり繰り返したりするなら、繰り返しから書いた自分を反省すべきだ.

Asynchronous


Asynchronousとは?asynchronousの意味は同期しないで、同時に存在します
では、なぜ非同期操作が必要なのでしょうか.
図には、クライアントとサーバが存在する場合の同期と非同期の動作が表示されます.

同期アクション
1.クライアントが何らかの要求を出す
2.サーバが要求を受けて処理する
3.クライアントが待機中
4.サーバ応答後処理開始
非同期タスク
1.クライアントからサーバに何らかの要求を送信する
2.サーバの稼働中は、クライアントは待機せずに他のタスクを実行します(作業を続行します).
3.サーバ上で作業を完了し、レスポンスが到来した場合、レスポンスを持って他の操作を行う
また、このような非同期処理方式は、作業時間全体を短縮することができる.

Asynchronousでの制御順序


私はAsyncがいいことを知っていますが、順序はどのように制御しますか?
次の例
const printString = (string) => {
    setTimeout(
      () => {
        console.log(string)
      }, 
      Math.floor(Math.random() * 100) + 1
    )
  }
 
  const printAll = () => {
    printString("A")
    printString("B")
    printString("C")
  }
  printAll()
printStringという名前の関数は、setTimeout法によって、ランダム時間後に入力されたstringconsole.logに撮影する.
A、B、CをprintAll関数に組み合わせて実行したらどうなりますか?

上記のように、毎回ランダムな順序で実行されます.
このようなランダムな順序ではなく、A>B>Cの順序で実行する場合、どのような方法がありますか?

Callback


1つ目の方法はコールバックです
const printString = function(string, callback) {
    setTimeout(function(){
        console.log(string)
        callback()
      }, 
      Math.floor(Math.random() * 100) + 1
    )
  }
 
  const printAll = () => {
    printString("A", function(){
      printString("B", function() {
        printString("C", function(){})
      })
    })
  }
上記の方法を使うと.

以上のように

Calbackメソッドを使用してエラーを処理する方法


タスクの処理中に必ずエラーが発生しますが、コールバックメソッドではどのようにエラーを処理しますか?
データとerrorはパラメータとして一緒に入るので、条件文(if)でエラーが発生した場合、エラーではなくnullにデータパラメータを変換する必要がある場合は、errorパラメータをnullに変換する必要があります
  fs.readFile(filePath, "utf8", function (err, data) {
    if (err) {
      callback(err, null);
    } else {
      callback(null, data);
    }
  });

コールバック問題


コールバックによる非同期関数の制御に問題があります.コールバックが多くなると可読性が低下し、callback hellと呼ばれます
以下のように作成
const printAll = () => {
  printString("A", function(){
    printString("B", function() {
      printString("C", function(){
        printString("D", function () {
          printString("D", function () {
            printString("D", function () {
              printString("D", function () {
                printString("D", function () {
                  printString("D", function () {
                    printString("D", function () {})
                  })
                })
              })
            })
          })
        })
      })
    })
  })
}
見るからに読みたくないコード.

Promise


コルバーハーラーから抜け出すのに役立つ技術があります
promiseはクラスでnew promiseでインスタンスを作成します
コールバック方式のprintString関数です
const printString = (string, callback) => {
    setTimeout(
      () => {
        console.log(string)
        callback()
      }, 
      Math.floor(Math.random() * 100) + 1
    )
  }

  const printAll = () => {
    //왠지 여기서 부터 callback hell이 일어날 것만 같은 느낌적인 느낌
    printString("A", () => {
      printString("B", () => {
        printString("C", () => {})
      })
    })
  }
  printAll() // now what do you expect?
コメントの後にコールバックhellが発生するようです
Promiseはコールバックをパラメータとして受け入れず、新しいpromiseインスタンスを返し、promiseはpromiseのコールバックを受け入れ、promiseはpromiseのコールバックをパラメータとして受け入れる
上記のコールバック方式をpromise方式に変更し、以下のようにします.
const printString = (string) => {
    return new Promise((resolve, reject) => {
      setTimeout(
        () => {
         console.log(string)
         resolve()
        }, 
       Math.floor(Math.random() * 100) + 1
      )
    })
  }

  const printAll = () => {
    //callback보다 평평해졌다!
    printString("A")
    .then(() => {
      return printString("B")
    })
    .then(() => {
      return printString("C")
    })
  }
  printAll()
callbackと同じ結果を返しますが、callback hellよりもフラットで読み取りやすいです.
promiseは、タスクが完了した後、.thenを介して次のタスクを続行できます.
また,callbackは毎回エラー処理を行う必要があるが,promiseは最後に.catch回でエラー処理を行うことができる.

約束にも地獄があるの?


return処理が正しく行われていない場合、以下に示すhellが生成される
function gotoCodestates() {
    return new Promise((resolve, reject) => {
        setTimeout(() => { resolve('1. go to codestates') }, Math.floor(Math.random() * 100) + 1)
    })
}

function sitAndCode() {
    return new Promise((resolve, reject) => {
        setTimeout(() => { resolve('2. sit and code') }, Math.floor(Math.random() * 100) + 1)
    })
}

function eatLunch() {
    return new Promise((resolve, reject) => {
        setTimeout(() => { resolve('3. eat lunch') }, Math.floor(Math.random() * 100) + 1)
    })
}

function goToBed() {
    return new Promise((resolve, reject) => {
        setTimeout(() => { resolve('4. goToBed') }, Math.floor(Math.random() * 100) + 1)
    })
}

gotoCodestates()
.then(data => {
    console.log(data)

    sitAndCode()
  //뭔가 또 hell인 것 같다...
    .then(data => {
        console.log(data)

        eatLunch()
        .then(data => {
            console.log(data)
            
            goToBed()
            .then(data => {
                console.log(data)
        
            })
        })
    })
})

最近新しく発売されたasync/await


es 8に追加
async/awaitは約束ですが、少し違うと言えます.
起動により、非同期関数は同期関数のように使用できます.
function gotoCodestates() {
    return new Promise((resolve, reject) => {
        setTimeout(() => { resolve('1. go to codestates') }, Math.floor(Math.random() * 100) + 1)
    })
}

function sitAndCode() {
    return new Promise((resolve, reject) => {
        setTimeout(() => { resolve('2. sit and code') }, Math.floor(Math.random() * 100) + 1)
    })
}

function eatLunch() {
    return new Promise((resolve, reject) => {
        setTimeout(() => { resolve('3. eat lunch') }, Math.floor(Math.random() * 100) + 1)
    })
}

function goToBed() {
    return new Promise((resolve, reject) => {
        setTimeout(() => { resolve('4. goToBed') }, Math.floor(Math.random() * 100) + 1)
    })
}

const result = async () => {
    const one = await gotoCodestates();
    console.log(one)

    const two = await sitAndCode();
    console.log(two)

    const three = await eatLunch();
    console.log(three)

    const four = await goToBed();
    console.log(four)
}

result();
結果はcallback,promiseと同様であったが,同期して発現できるためコードの毒性が高かった.