非同期Promise、async&await

21767 ワード

コードを同期して実行するJSでは、データを受信するのに10秒かかるコードがあれば、以降のコードが完了するのを待つ必要があります.
function fetchUser(){
        //do network request in 10sec...
        return "ellie"
}

const user = fetchUser();
//동기적으로 실행되기 때문에 아래의 코드들은 
//10초동안 기다려야 한다

//... 여러 코드들...
console.log(user)
このコードの後ろにウェブUIが表示されるコードがある場合、上記の操作が完了するまでデータは入らず、空白のページしか見えません.
したがって、非同期処理では、データ受信時に表示部ではなくUIを最初に表示するための非同期操作が必要となり、Promiseおよびasync&awaitが必要となる.

Promise


promiseオブジェクトはネットワーク通信であり,データの準備さえできれば関数からResult値を得ることができる.
ただし、通常の承諾オブジェクトを返すには、解析関数またはコールバック拒否関数を使用する必要があります.したがって、then関数から承諾オブジェクトのResult値を取得できます.
このとき返されるpromiseオブジェクト値の状態は「完了」、Resultはコールバック関数のパラメータ値です.
コールバック関数(resolve、reject)を使用します.
function fetchUser(){
    return new Promise ((resolve, reject) => {
        //do network request in 10sec...
        resolve('ellie')
    })
}//promise 객체를 return

const user = fetchUser();
//데이터를 비동기적으로 받아온다
user.then(console.log)
//데이터가 준비되었을 때 비동기적으로 실행된다
console.log(user)//async.js: 14

return文を直接使用すると、通常のpromiseオブジェクトを返すことができないため、then関数からpromiseオブジェクトのresult値を取得することはできません.
このとき返されるpromiseオブジェクト値の状態は「pending」、Resultは「undefined」です.
戻り文を使用する場合
function fetchUser(){
    return new Promise ((resolve, reject) => {
        //do network request in 10sec...
        return "ellie"
    })
}//promise 객체를 return

const user = fetchUser();
user.then(console.log)
console.log(user)//async.js: 14

n/a.結論


約束の中で必ず決意や拒否で終わらせなければならない.

async & await


asyncを使用するとpromiseを使用することなく、簡単に非同期で使用できます.
関数の前にasyncキーワードを付けると、関数のコードブロックが自動的にpromiseに変換されます.
async function fetchUser(){
        //do network request in 10sec...
        return "ellie"
}

const user = fetchUser();
user.then(console.log);
console.log(user);

awaitがasyncとともに使用される場合、同期コードを記述するように非同期タスクを記述できます.awaitはasync付きの関数でのみ使用できます.
awaitは非同期タスク内で同期タスクを実行するために使用され、promise channingと同じ用途に使用されます.
function delay(ms){ 
    return new Promise(resolve => setTimeout(resolve, ms));
}//ms 후에 resolve를 호출하는 promise 를 리턴

async function getApple(){
    await delay(3000);//await 은 delay 함수가 끝날때까지 기다린다(동기적인 작업)
    return "★";//결과적으로 3초후에 return 됨
}
上記のコードがある場合、
settimeoutは非同期関数であるためdelay(3000)までawaitを書かなかった場合、settimeoutのコールバック関数resolveを3秒後に実行しても非同期処理が実行されるため、getApple関数を呼び出すと即座にコールバックが実行され、"★"形状が出力される.
ただし、delay(3000)の前にawaitを追加すると、非同期操作でも完了するまで待たなければならないため、非同期操作を同期操作として使用することができる.したがってsettimeout関数が終了する3秒後には、戻り文が実行され、"★"形状が出力されます.
この作業は、以前作成したMovieAppから映画情報をロードするために使用することができ、この感覚を使用することができます.
useEffect(()=> {
	(async function(){ 
      const List = await axios.get("URL)';
	  setList(List)                                        
}, [])
いずれにしても、再び戻ってくると、プミスもあまりにも重なり合ってリンクされ、コールバック地獄のような問題(pickFruits関数)が発生します.
function delay(ms){ 
    return new Promise(resolve => setTimeout(resolve, ms));
}//ms 후에 resolve를 호출하는 promise 를 리턴

async function getApple(){
    await delay(1000);//await 은 delay 함수가 끝날때까지 기다린다(동기적인 작업)
    return "★";//결과적으로 3초후에 return 됨
}

async function getBanana(){// async & await 버전(동기적인 코드를 쓰는 것처럼 작성 가능)
    await delay(1000);
    return "●"
}
/*
function getBanana2(){
    return delay(3000)
    .then(()=> "●")//promise chaining 해야한다.
}
*/	
function pickFruits(){
    return getApple().then(apple => {
        return getBanana1().then(banana => `${apple} + ${banana}`)
    })
}

pickFruits().then(console.log)//★ + ● (2초뒤)
したがって,Promisはasync&awaitを用いて簡単な処理も可能である.
=>同期記述コードのように書き込み、return値も自然に取得できるので非常に簡単です.また,エラー処理にはtry&catchなどの従来の手法を用いることもできる.
async function pickFruits(){
    const apple = await getApple();
    const banana = await getBanana();
    return `${apple} + ${banana}`
}
pickFruits().then(console.log)//★ + ● (2초뒤)
ここに問題があります.
以上のコードはバナナとリンゴをそれぞれ待っていて、全部で2秒かかります.でもバナナとリンゴは関係ないので待つ必要はありません.したがって、並列に使用できます.
async function pickFruits(){
    //프로미스를 만들면 만들어지는 즉시 promise안에 있는 코드블럭이 (병령적으로, 동시)실행된다.
    const applePromise = getApple();
    const bananaPromise = getbanana();
    //그 후 await 로 동기화 시켜주면 된다.
    const apple = await applePromise;
    const banana = await bananaPromise;
    return `${apple} + ${banana}`;
}
pickFruits().then(console.log)//★ + ● (1초뒤)
Promise.all APIも使用できます.
Promise.すべてのPromisが受信されるまで、all APIでPromis配列が渡されます.その後、受信した配列が渡され、その配列が複数の方法として使用されます.
function pickAllFruits(){
    return Promise.all([getApple(),getBanana()])
    .then(fruits => fruits.join(' + '))
}
pickAllFruits().then(console.log)//★ + ● (1초뒤)