프론트엔드 개발일지 #26 - Promise, 비동기 키워드, 대기 키워드, 비동기 함수 오류 처리

조아라·2024년 10월 24일
0
post-thumbnail

Promise라는 마법

// fakeRequestPromise('yelp.com/api/coffee/page1')
//     .then(() => {
//         console.log("IT WORKED!!!!!! (page1)")
//         fakeRequestPromise('yelp.com/api/coffee/page2')
//             .then(() => {
//                 console.log("IT WORKED!!!!!! (page2)")
//                 fakeRequestPromise('yelp.com/api/coffee/page3')
//                     .then(() => {
//                         console.log("IT WORKED!!!!!! (page3)")
//                     })
//                     .catch(() => {
//                         console.log("OH NO, ERROR!!! (page3)")
//                     })
//             })
//             .catch(() => {
//                 console.log("OH NO, ERROR!!! (page2)")
//             })
//     })
//     .catch(() => {
//         console.log("OH NO, ERROR!!! (page1)")
//     })


// THE CLEANEST OPTION WITH THEN/CATCH
// RETURN A PROMISE FROM .THEN() CALLBACK SO WE CAN CHAIN!
fakeRequestPromise('yelp.com/api/coffee/page1')
    .then((data) => {
        console.log("IT WORKED!!!!!! (page1)")
        console.log(data)
        return fakeRequestPromise('yelp.com/api/coffee/page2')
    })
    .then((data) => {
        console.log("IT WORKED!!!!!! (page2)")
        console.log(data)
        return fakeRequestPromise('yelp.com/api/coffee/page3')
    })
    .then((data) => {
        console.log("IT WORKED!!!!!! (page3)")
        console.log(data)
    })
    .catch((err) => {
        console.log("OH NO, A REQUEST FAILED!!!")
        console.log(err)
    })

이렇게 위의 코드를 Promise 객체를 이용해서 엄청나게 간결하게 들여쓰기를 위 코드처럼 하지않고 가독성이 좋게 적어 낼 수 있다. 어디선가 막히면 catch 를 통해서 오류를 나타내 줄 수 있다.

const fakeRequest = (url) => {
    return new Promise((resolve, reject) => {
        const rand = Math.random();
        setTimeout(() => {
            if (rand < 0.7) {
                resolve('YOUR FAKE DATA HERE');
            }
            reject('Request Error!');
        }, 1000)
    })
}

fakeRequest('/dogs/1')
    .then((data) => {
        console.log("DONE WITH REQUEST!")
        console.log('data is:', data)
    })
    .catch((err) => {
        console.log("OH NO!", err)
    })

resolve와 reject될때 출력이 어떻게 될 지 잘 나온다 !
다른 예시를 보자면


// const delayedColorChange = (newColor, delay, doNext) => {
//     setTimeout(() => {
//         document.body.style.backgroundColor = newColor;
//         doNext && doNext();
//     }, delay)
// }

// delayedColorChange('red', 1000, () => {
//     delayedColorChange('orange', 1000, () => {
//         delayedColorChange('yellow', 1000, () => {
//             delayedColorChange('green', 1000, () => {
//                 delayedColorChange('blue', 1000, () => {
//                     delayedColorChange('indigo', 1000, () => {
//                         delayedColorChange('violet', 1000, () => {

//                         })
//                     })
//                 })
//             })
//         })
//     })
// });

//Promise를 사용해서 이 코드를 정리한다면,
const delayedColorChange = (color, delay) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            document.body.style.backgroundColor = color;
            resolve();
        }, delay)
    })
}


delayedColorChange('red', 1000)
    .then(() => delayedColorChange('orange', 1000))
    .then(() => delayedColorChange('yellow', 1000))
    .then(() => delayedColorChange('green', 1000))
    .then(() => delayedColorChange('blue', 1000))
    .then(() => delayedColorChange('indigo', 1000))
    .then(() => delayedColorChange('violet', 1000))

.then을 써주지 않으면, 코드는 위에서 아래로 작동하기 때문에 결국 보라색만 남게 된다. 그때 .then을 사용해주면 차례대로 색이 변하는걸 볼 수 있다.
이 Promise에는 전부다 성공이어서 성공과 실패의 갈림길도 없다.

비동기 키워드

Async
깔끔하게 만들어준다 👀 함수를 비동기 함수로 선언하는 함수이다. 함수 앞에 async를 입력하여 비동기로 만들면 함수는 자동적으로 promise를 반환한다.

const sing = async () => {
    throw "OH NO, PROBLEM!"
    return 'LA LA LA LA'
}

sing()
    .then(data => {
        console.log("PROMISE RESOLVED WITH:", data)
    })
    .catch(err => {
        console.log("OH NO, PROMISE REJECTED!")
        console.log(err)
    })

함수가 값을 반환할 때 resolve 상태로 반환이 될 것이다. 여기서 반환 값이 'LA LA LA LA'이다. 이게 어떤식으로 유용하냐면, 아래 코드처럼 sing().then(()=>{})라고 적어줄때 비동기적으로 작동하게 된다. 프라미스가 정상적으로 이행되면 promise는 프라미스 객체의 result에 저장된 값을 반환하고, 반면 프라미스가 거부되면 마치 throw문을 작성한 것처럼 에러가 던져집니다.throw "OH NO, PROBLEM!"로 비동기 함수에 던져진 에러를 잡아주면 promise는 rejected된다.


const login = async (username, password) => {
    if (!username || !password) throw 'Missing Credentials'
    if (password === 'corgifeetarecute') return 'WELCOME!'
    throw 'Invalid Password'
}

login('todd', 'corgifeetarecute')
    .then(msg => {
        console.log("LOGGED IN!")
        console.log(msg)
    })
    .catch(err => {
        console.log("ERROR!")
        console.log(err)
    })

대기 키워드

Await
이 키워드는 비동기 코드를 쓰면서 동기적으로 보이게 해준다😯 기다리게 하는 역할인데, Promise값을 반환 할 때까지 기다리기 위해 비동기 함수의 실행을 일시 정지 시킨다. 비동기 함수에서만 적용돠기 때문에 async와 짝궁이다 !

const delayedColorChange = (color, delay) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            document.body.style.backgroundColor = color;
            resolve();
        }, delay)
    })
}

// delayedColorChange('red', 1000)
//     .then(() => delayedColorChange('orange', 1000))
//     .then(() => delayedColorChange('yellow', 1000))
//     .then(() => delayedColorChange('green', 1000))
//     .then(() => delayedColorChange('blue', 1000))
//     .then(() => delayedColorChange('indigo', 1000))
//     .then(() => delayedColorChange('violet', 1000))


async function rainbow() {
    await delayedColorChange('red', 1000)
    await delayedColorChange('orange', 1000)
    await delayedColorChange('yellow', 1000)
    await delayedColorChange('green', 1000)
    await delayedColorChange('blue', 1000)
    await delayedColorChange('indigo', 1000)
    await delayedColorChange('violet', 1000)
    return "ALL DONE!"
  
  // rainbow().then(() => console.log("END OF RAINBOW!"))
  
  async function printRainbow() {
    await rainbow();
    console.log("END OF RAINBOW!")
}

printRainbow();
}

앞에서 색을 바꿔주는 코드를 봤는데, 이렇게 적어 줄 수 있다.

비동기 함수 오류 처리

그리고 비동기 함수에서 실패를 하면 어떻게 처리를 했을까?

const fakeRequest = (url) => {
    return new Promise((resolve, reject) => {
        const delay = Math.floor(Math.random() * (4500)) + 500;
        setTimeout(() => {
            if (delay > 2000) {
                reject('Connection Timeout :(')
            } else {
                resolve(`Here is your fake data from ${url}`)
            }
        }, delay)
    })
}


async function makeTwoRequests() {
    try {
        let data1 = await fakeRequest('/page1');
        console.log(data1);
        let data2 = await fakeRequest('/page2');
        console.log(data2);
    } catch (e) {
        console.log("CAUGHT AN ERROR!")
        console.log("error is:", e)
    }

}
profile
끄적 끄적 배운 걸 적습니다 / FRONT-END STUDY VELOG

0개의 댓글