[JS/Node]非同期


iterator


コールバック関数


別の関数(A)に渡す伝達パラメータ(B)
function B() {
  console.log("called at the back!");
}
function A(Callback) {
  callback(); // callback === B
}

A(B);
関数Aは、関数B(コールバック関数)を同期または非同期で実行することができる.

コンテキストコールバック関数


1)繰り返し実行する関数(反復器)


例)each、map、filterメソッド等
[1, 2, 3].map((element, index) => {
	return element* element;
});

2)イベント駆動の関数(イベントハンドラ)

document.querySelector('#btn').addEventListener('click', (e) => { 
  console.log('button clicked'); 
});

コールバック関数の注意事項


コールバック関数は、接続関数そのものであり、接続関数の実行ではありません.
function handleClick() {
  console.log('button clicked');
}

/*함수 자체를 연결하는 옳은 예*/
document.querySelector('#btn').onclick = handleClick; // (o)
document.querySelector('#btn').onclick = () => {handleClick();} // (o)
document.querySelector('#btn').onclick = handleClick.bind(); // (o)

/*함수 실행을 연결하는 잘못된 예*/
document.querySelector('#btn').onclick = handleClick(); // (o)

handleClick(); // handleClick의 실행 결과 === 'undefined'
	       // return 값이 없기 때문이다.
               // 따라서, 마지막 코드는 onclick에 'undefined'를 연결한 것과 마찬가지가 된다. 

blocking


電話番号
電話に出るには、仕事をやめなければなりません.
リクエスト(受信)の結果(受信)が同時に発生します.

non-blocking


non-blocking==文字
リクエストの結果は同時に発生しません.
非同期発生
お客様はアメリカンコーヒーを注文します.「要求」
「要求」はブロックされていません.
応答は非同期です.
アメニティが完成すると、スタッフがお客様を呼びます.
完了後==="イベント"
アメニティが完成すると、スタッフがお客様を呼びます.
コール客==「イベントハンドラ」=「コールバック関数」

同期コード

function waitSync(ms){
    var start = Date.now();
    var now = start;
    while(now - start < ms) {
        now = Date.now();
    }
} // 현재 시각과 시작 시각을 비교하며 ms 범위 내에서 무한 루프를 도는 blocking 함수입니다.

function drink(person, coffee){
    console.log(person + '는 '+ coffee + '를 마십니다');
}

function orderCoffeeSync(coffee){
    console.log(coffee + '가 접수되었습니다');
    waitSync(4000);
    return coffee;
}

let customers = [{
    name: 'Steve',
    request: '카페라떼'
}, {
    name: 'John',
    request: '아메리카노'
}];

// call synchronously
customers.forEach(function(customer) {
    let coffee = orderCoffeeSync(customer.request);
drink(customer.name, coffee);
});

ひどうきコード

function waitAsync(callback, ms){
    setTimeout(callback, ms);
    // 특정 시간 이후에 callback함수가 실행되게금 하는 브라우저 내장 긴능입니다.
}

function drink(person, coffee) {
    console.log(person + '는 ' + coffee + '를 마십니다');
}

function orderCoffeeSync(coffee) {
    console.log(coffee + '가 접수되었습니다');
    waitSync(2000);
    return coffee;
}

let customers = [{
    name: 'Steve',
    request: '카페라떼'
}, {
    name: 'Jhon',
    request: '아메리카노'
}];

function orderCoffeeAsync(menu, callback){
    console.log(menu + '가 접수되었습니다');
    waitAsync(function() {
        callback(menu);
    }, 2000);
}

// call asynchronously
customers.forEach(function(customer) {
    orderCoffeeAsync(customer.request, function(coffee) {
    drink(customer.name, coffee);
    });
});

非同期キーケース


サーバへのリソースのリクエストと応答
1.fetch API-リクエストサーバ
2. AJAX(XHR)

「非同期」なのでロードできますが、他の構成部品を操作できます.

非同期の原理-イベントサイクルについて


event loop

async


JavaScript実行の原理===「非同期」
質問:順序を制御できません.
const printString = (string) => {
    setTimeout( () => {
        console.log(string);
    },
    Math.floor(Math.random() * 100) + 1
    )
}

const printAll = () => {
    printString("A")
    printString("B")
    printString("C")
}
printAll(); // what do you expect? Random

コールバック関数


非同期の順序を制御する必要があります.
const printString = (string, callback) => {
    setTimeout( () => {
        console.log(string);
        callback();
    },
    Math.floor(Math.random() * 100) + 1
    )
}

const printAll = () => {
    printString("A", () => {
        printString("B", () => {
            printString("C", () => {})
        })
    })
}    
printAll(); // now, what do you expect? A, B, C
質問:callback hellが表示されます.(複雑)

promise


resolve()コマンドとreject()コマンドで次の操作に移動したり、エラーを処理したりできます.
最初のタスクが完了すると、.then()を介して次のタスクを実行できます.
コールバック関数とは異なり、エラー処理が行われた場合.
最後のchainのみで.catch()でエラー処理を行うことができます.
const printString = (string) => {
    return new Promise((resolve, reject) => {
    setTimeout(
        () => {
            console.log(string);
            resolve();
        },
        Math.floor(Math.random() * 100) + 1
    )
    
})
}
                       
                       
const printAll = () => {
    printString("A")
    .then(() => {
        return printString("B")
    })
    .then( () => {
        return printString("C")
    })
}    
printAll(); // now, what do you expect?
動作はコールバックと同じであるが,可読性が向上していることがわかる.
質問:hellの発生を承諾する
function gotoCodestates() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('1. go to codestates') }, 100)
    })
}

function sitAndCode() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('2. sit and code') }, 100)
    })
}

function eatLunch() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('3. eat lunch') }, 100)
    })
}

function goToBed() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('4. goToBed') }, 100)
    })
}

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

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

promise Chaining

function gotoCodestates() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('1. go to codestates') }, 100)
    })
}

function gotoCodestates() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('1. go to codestates') }, 100)
    })
}

function sitAndCode() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('2. sit and code') }, 100)
    })
}

function eatLunch() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('3. eat lunch') }, 100)
    })
}

function goToBed() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('4. goToBed') }, 100)
    })
}

gotoCodestates()
.then(data => {
    console.log(data);
    return sitAndCode()
})
.then(data => {
    console.log(data);
    return eatLunch();
})
.then(data => {
    console.log(data);
    return goToBed();
})
.then(data => {
    console.log(data);
})

async await


承諾の関数について、resultasync関数に変更します.awaitを使用すると、同期関数として非同期関数を使用できます.
promiseは一種ですが、promise関数よりもコードの毒性が大きいです.
function gotoCodestates() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('1. go to codestates') }, 100)
    })
}

function gotoCodestates() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('1. go to codestates') }, 100)
    })
}

function sitAndCode() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('2. sit and code') }, 100)
    })
}

function eatLunch() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('3. eat lunch') }, 100)
    })
}

function goToBed() {
    return new Promise((resolve, reject) => {
    setTimeout( () => { resolve('4. goToBed') }, 100)
    })
}

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();

Promise.all()メソッド


ループ可能なオブジェクトに与えられたすべてのプロセスが実行された後、またはプロセスが許可されていないときに実行されたプロセスを返します.整列されたプロセスが拒否された場合、戻り形式では、最初の拒否されたプロセスの理由を使用して拒否されます.