언어&프레임워크/JavaScript

promise(in JavaScript)

밍풀 2023. 6. 5. 20:13

promise ; 약속, 자바스크립트에서 비동기 간편하게 처리할 수 있게 하는 오브젝트

정해진 기능 수행하고 나서 정상적으로 기능이 수행되면 성공의 메세지와 함께 결과값을 전달

만약 기능을 수행하다가 예상치 못한 문제가 발생하면 에러를 전달

 

예를들어 준비중인 강의가 언제 오픈될지 모르는 데 관심학생은 미리 등록하는 시스템에서 사용.

 

시간 지난 후 코스가 오픈되면 등록한 학생에게 메일 공지를 보냄

 

수업이 이미 오픈된 뒤에 철수가 뒤늦게 사전공지 창을 발견

뒤늦게 등록하지만 수업이 이미 오픈되었기 때문에 기다릴 필요없이 바로 메일 공지

수업에 바로 참여 가능해짐

 

콜백을 쓰지 않고 프로미스 오브젝트를 통해 비동기 코드 깔끔하게 처리하기

 

프로미스는 자바스크립트 안에 내장되어진 오브젝트

비동기적인 것을 처리할때 콜백함수 대신 유용하게 쓸 수 있음

 

포인트 2가지 

1. State 

pending state

수행중

fulfiled state

수행완료,  수행 다 완료해서 성공했는지 실패했는지

rejected

파일을 찾을수없거나 네트워크에 문제

 

2.  producer 와 consumer 의 차이점 알기

Producer

원하는 기능을 수행해서 해당하는 데이터를 만들어내는, 데이터를 제공하는  

Consumer 

원하는 데이터를 소비하는, 제공된 데이터를 쓰는

 

1. Promise 만들기 

 

1. Producer 

 

원하는 기능을 비동기적으로 실행하는 프로미스 만들기

 

기능을 정상적으로 수행해서 최종 데이터를 전달하는 resolve

기능을 수행하다가 중간에 문제가 생기면 호출하는 reject 

위 두가지를 받는 콜백함수를 인자로 받음 

 

네트워크에서 데이터를 받거나, 파일에서 무언가 큰 데이터를 읽어오는 과정은

시간이 꽤 걸림 그런걸 동기적으로 처리하면 다음 라인코드가 실행되지 않기에 

시간걸리는건 비동기적으로 처리하는게 좋음

따라서 네트워크 처리, 파일읽기는 비동기적으로 처리하는게 좋다.

 

 

위코드 실행시 바로 doing something 이 출력됨

=프로미스를 만드는 순간 전달한 콜백함수가 바로 자동적으로 실행됨 유의 !!

 

프로미스 안에 네트워크 통신을 하는 코드를 작성했다면 

프로미스가 만들어 지는 순간 바로 네트워크 통신을 수행하게 됨

= 만약 네트워크 요청을 사용자가 요구했을때만 해야된다면 이런식으론 

요구하지도 않았는데 불필요한 통신이 일어나게 됨

 

프로미스 안에서 네트워크 통신을 하는 것처럼 셋타임아웃을 이용해서 시간딜레이주기

1
2
3
4
5
6
7
8
9
10
11
12
13
//1.producer
 
const promise = new Promise((resolve, reject) => {
    //doing somet hard work...
    console.log('doing something');
    setTimeout(() => {
        resolve('min');
    }, 2000);
});
 
 
 
 
cs

어떤 일을 2초정도 하다가 잘 마무리해서 resolve 콜백함수 호출해서 min 이 라는 데이터전달

 

2. promise 사용하기 

then, catch, finally 를 통해 값을 받아 올 수 있음

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//1.producer
 
const promise = new Promise((resolve, reject) => {
    //doing somet hard work...
    console.log('doing something');
    setTimeout(() => {
        resolve('min');
    }, 2000);
});
 
 
//2. consumer(then, catch, finally)
 
promise.then((value)=>{
    console.log(value);
});
 
 
 
cs

promise 가 잘 수행하면 값을 받아서 어떠어떤일을 할거야

value는 promise가 잘 수행해서 resolve 콜백함수에서 전달된 min이라는 데이터

min 이 출력됨

 

프로미스가 정상적으로 수행되어서 resolve 라는 콜백함수를 통해서 전달한 값이 

value 파라미터로 전달되어져서 들어오게 됨

 

만약 네트워크하다가 실패해서 reject를 호출한다면?

보통 error오브젝트 통해 값을 전달

error 클래스는 자바스크립트에서 제공하는 오브젝트

보통 error 오브젝트에는 어떤에러가 발생했는지 이유를 작성함

then으로 성공적인 케이스만 다뤘기에 잡히지않았다(uncaught) 의

위와 같은 에러가 뜨게됨 

=> catch를 이용해 에러발생시 처리를 다루기

위와 같이 에러가 콘솔에 출력됨

 

finally 

성공하던 실패하던 상관없이 무조건 마지막에 호출됨

 

3. promise 연결하기

 

 

5가 출력됨

then에서 return을 또 promise로 할 수 있음

 

4. 오류 처리하기

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//4. Error handling
const getHen = ()=> 
    new Promise((resolve, reject)=>{
        setTimeout(()=> resolve('chicken'), 1000);
    });
 
const getEgg = hen =>
    new Promise((resolve, reject)=>{
        setTimeout(()=> resolve(`${hen}=> egg`),1000);
    });
 
 
const cook = egg =>
    new Promise((resolve, reject)=>{
        setTimeout(()=> resolve(`${egg}=> fried egg`),1000);
    });
 
getHen()
.then(hen => getEgg(hen))
.then(egg => cook(egg))
.then(meal => console.log(meal));
cs

chicken=> egg=> fried egg 출력

 

 

만약 달걀을 받아오는 과정에서 네트워크에 문제가 생겨 실패한다면?

(getEgg부분)

맨 밑에 .catch를 붙이면, 에러가 발생했지만 에러가 젤 밑으로 전달되며 잡혀짐

 

달걀을 받아올때 문제가 생긴다면 다른재료로 대체 하고싶다면?

getEgg에 문제가 생겨도 전체적인 프로미스 체인에 문제가 발생하지 않도록

위에서 발생하는 문제 대처하기 위해 아래에 catch를 바로작성해서 바로해결

 

 

catch 위치가 위와 같은 경우에는 bread 가 출력

 

 

5. 콜백 헬을 프로미스로 재단장

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class UserStorage{
    loginUser(id, pass){
 
       return new Promise((resolve, reject)=>{
 
            setTimeout(()=>{
                if(
                    (id==='min'&& pass==='dream'||
                    (id==='coder'&& pass==='great')
                ){
                    resolve(id);
                }else{
                    reject(new Error('not found'));
                }
     
            },2000);
 
        });
    }
 
    getRoles(user){
 
        return new Promise((resolve, reject)=>{
            setTimeout(()=>{
                if(user==='min'){
                    resolve({name : 'min', role : 'admin'})
                }else{
                    reject(new Error('no access'));
                }
            }, 1000);
 
        })
    }
}
 
const userStorage = new UserStorage();
let id = prompt('what is your id ? ');
let password = prompt('what id your password?');
 
userStorage.loginUser(id, password)
.then(userStorage.getRoles)
.then((user)=> alert(`hello ${user.name} your role is ${user.role}`))
.catch(console.log)
cs

 

좌 ;프로미스 사용 우; 콜백지옥