웹개발

Promise 프라미스, 비동기 처리

미스터몽키 2018. 12. 18. 02:27

콜백(callback) 개념을 익히고 나니 콜백지옥으로 인한 코드 가독성이 너무 떨어진다.

웹의 특성이라 어쩔수 없이 비동기 처리해야 하는 상황이라 이해해야한다.

C, Delphi 등에 너무 익숙한 개발자들은 처음 이해하는데 고생이 많을 것 같다.


그나마 Promise (프라미스) 가 코드 가독성이 좋다고하여  배워본다.


콜백이 비동기함수안에 다시 비동기함수를 계속해서 직렬(Promise chain, 프라미스 체인)로 함수를 작성한다고 하면 프라미스는 병렬로 작성한다고 볼수 있다. 

동기식 표현에 가깝게 하여 가독성을 좋게 하려는 뜻이다.


1. 콜백표현


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
async1(function (err, value1) {
    if (err) {
        console.log(err);
        return;
    }
    async2(function (err, value2) {
        if (err) {
            console.log(err);
            return;
        }
        async3(function (err, value3) {
            if (err) {
                console.log(err);
                return;
            }
            async4(function (err, value4) {
                // 지옥 속으로...
            });
        });
    });
});
cs



2. Promise 프라미스


프라미스 Promise  "약속할게 기다리고 있어 결과는 나중에 알려줄게~"


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
// 프라미스1 선언부
const p1 = new Promise((resolve, reject) => {
    async1((err, param) => {
        if(err) {
            reject(err)
        }
        resolve(param)
    })
})
 
// 프라미스2 선언부
const p2 = new Promise((resolve, reject) => {
    async2((err, param) => {
        if(err) {
            reject(err)
        }
        resolve(param)
    })
})
 
// 디스플레이 함수
const onDisplay = () => {
    res.json({
        success: true,
        message: '성공~'
    })
}
 
// 에러함수 선언
const onError = (error) => {
    res.status(403).json({
        success: false,
        message: '!에러'
    })
}
 
//프라미스 실행부
p1
.then(p2)
.then(display)
.catch(onError) 
 

cs



 (프라미스 리턴값 있는 방식)

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
44
45
46
// 프라미스1 선언부 (함수식)
const p1 = (parma) => {
    return  new Promise((resolve, reject) => {
        async1((err, param) => {
            if(err) {
                reject(err)
            }
            resolve(param)
        })
    })
}
 
// 프라미스2 선언부 (함수식)
const p2= (parma) => {
    return  new Promise((resolve, reject) => {
        async2((err, param) => {
            if(err) {
                reject(err)
            }
            resolve(param)
        })
    })
}
 
// 디스플레이 함수
const onDisplay = () => {
    res.json({
        success: true,
        message: '성공~'
    })
}
 
// 에러함수 선언
const onError = (error) => {
    res.status(403).json({
        success: false,
        message: '!에러'
    })
}
 
//프라미스 실행부 (함수식)
p1('여긴파라미터')
.then(p2)
.then(display)
.catch(onError) 
 
cs


 (프라미스 리턴값 있는 방식2 )

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
router.get('/pm2/:a'function(req,res){
    //프라미스 체인을 위해 리턴 함수로 프라미스를 만들자
    const p1 = (text1) => {
        return new Promise((resolve, reject) => {
            let n = Number(text1)
            // console.log(n)
            if (isNaN(n)) {
                reject('숫자아님')  // 프라미스가 거부되었을 때 리턴되는 값은 '숫자아님' 이다.
            } else {
                resolve(text1)  // 프라미스가 해결되었을 때 리턴되는 값은 text1 이다.
            }
        })
    }
 
    const p2 = (text2) => {
        return new Promise((resolve, reject) => {
            let n = Number(text2)
            if (n <= 10) { 
                resolve(text2 + ' 숫자는 10이하입니다.')
            } else {
                reject(text2 + ' 숫자는 10초과입니다.')
            }    
        })
    }
 
    p1(req.params.a)
    .then(p2)          //then함수는 바로 앞단 프라미스가 resolve일때 실행된다. 앞단이 프라미스가 아닐때는 안된다.
    .then((text) => {
        res.send('then안: ' + text)  // then안: 5 숫자는 10이하입니다.
    })
    .catch((text) => {  // catch함수는 여러 앞단의 프라미스가 reject 이거나 오류가 발생했을 때 실행된다.
        res.send('catch안: ' + text)  // catch안: 숫자아님
    })
});
cs



참고 링크