혼자 적어보는 노트

[Javascript] Promise에 대한 이해 본문

Javascript

[Javascript] Promise에 대한 이해

jinist 2021. 11. 23. 00:38

Promise

 

서버에 요청을하거나 큰데이터를 읽거나 하는 것을 동기적으로 처리할 경우
다음 작업을 하는데에 시간이 걸린다.

그래서 네트워크 통신이나 파일을 읽는 등 시간이 걸리는 작업을 할 경우에는

비동기적(Asynchronous)으로 처리를 하는것이 좋다.

 

비동기 처리로는 promise가 있고 async await이 있는데 일단 promise부터 알아보자.

let promise = new Promise(function(resolve, reject) {
  // executor()
});

new promise가 만들어 질 때 executor(실행함수)가 자동적으로 실행된다.
executor는 처리 성공 여부에 따라 resolve나 reject를 호출하게 된다.

 

resolve(value) - 요청한 일이 성공적으로 끝난 경우 그 결과를 나타내는 value와 함께 전달
reject(error) - 에러 발생 시 에러 객체를 나타내는 error와 함께 전달

 

위 함수 2개는 자바스크립트 엔진이 미리 정의한 함수이며 따로 만들 필요가 없다.

하지만 resolve와 reject 중 하나는 반드시 호출해야 한다.

 

 

promise객체의 상태 변화

promise의 state는 pending으로 시작하며 상태를 둘 중 하나로 변경한다.

 

resolve(value)호출 시

state: "fulfilled"

result: value

 

reject(error)호출 시

state: "rejected"

result: error

 

setTimeout 함수를 이용하여 executor함수에서 시간이 걸리도록 구현해보자.

 

let promise = new Promise((resolve, resject) =>{
    //executor 함수는 자동 실행됨
    setTimeout(()=>{ resolve("success")}, 1000);
})

executor함수에 1초뒤 resolve("success")를 호출하도록 만들었다.

그렇다면 위 코드의 상태는 아래와 같다.

 

state: "fulfilled"

result: "success"

 

이렇게 처리가 끝난 프라미스를 처리된(settled) 프라미스라고 말한다.

그렇다면 호출한 result는 어떻게 접근을 할까?

성공적으로 이행 했을 경우 어떠한 값을 전달하고 싶을 때.

 

result에 대한 접근

 

.then

promise에서 가장 기본이 되는 메서드.

let promise = new Promise((resolve, resject) =>{
    //executor 함수는 자동 실행됨
    setTimeout(()=>{ resolve("success")}, 1000);
});

promise.then(
    (result) => console.log(result), // success
    (error) => console.log(error)
);

.then의 첫번 째 인수는 프라미스가 이행 되었을 때 실행되는 함수이고

두 번째 인수는 프라미스가 거부되었을 때 실행되는 함수이다.

즉, resolve로 "success"를 보냈으니 .then의 result부분이 실행되며 console에는 "success"이 출력된다.

 

 

.catch

promise에서 에러가 발생한 경우를 다루는 메서드이다.

let promise = new Promise((resolve, reject) =>{
    //executor 함수는 자동 실행됨
    setTimeout(()=>{ reject(new Error("Error!")) }, 1000);
});

promise
.then(result => console.log(result))
.catch(error=> console.log(error));

보통 .then과 함께 사용하지만 에러만 발생한 경우만 다루고 싶을 때는 .catch만 단독으로 사용 가능하다.

 

.finally

프라미스가 처리된 후 성공 실패의 여부와 관계없이 실행되는 메서드

promise
.then(result => console.log(result))
.catch(error=> console.log(error))
.finally(() => console.log("End")) //항상 출력

finally에는 인수가 없다. 즉 성공과 실패의 여부를 알수 없다.

꼭 마지막에 호출할 필요는 없다. then과 catch사이에서도 호출이 가능하다.

 

 

위의 배운 것들을 토대로 userList의 데이터를 활용하여

로그인 하는 과정을 짜보았다. 물론 실제 데이터가 아니기 때문에

tetTimeout으로 임시로 시간이 걸리게끔 진행했다.

const userList = [
    { id: 'jay', password: '1234'},
    { id: 'hey', password: '1234'},
    { id: 'hello', password: '1234'}
]

const loginUser = (id, password)=> {
    return new Promise((resolve, reject)=>{
        setTimeout(()=>{
            if(userList.find((item)=> item.id === id && item.password === password)){
                resolve(`${id}님 환영합니다.`);
            }else{
                reject(new Error('잘못된 정보입니다.'));
            }
        },1000);
    })
}

const id = prompt("Id를 입력해주세요.");
const password = prompt("Password를 입력해주세요.");

loginUser(id, password)
.then(result=> alert(result))
.catch(alert);

 

 

 

Comments