민한의 블로그

study 본문

728x90
반응형

Callback Hell

1
2
3
4
5
6
7
8
9
const addOneTo = function(number, callback){
    let result = number + 1;
    if(callback)
        callback(result);
}
// 5 + 1 = 6
addOneTo(5function(res){
    console.log(res);
})
cs

여기서는 파라미터를 number를 받고 콜백을 통해 number+1을 반환하는 addOneTo라는 메서드를 정의하였습니다.

이것은 단순한 예이며 보통 I / O 또는 시간이 많이 걸리는 작업은 콜백을 사용하여 수행됩니다. 

어쨌든이 메서드를 정의한 다음 호출하고 콜백을 통해 결과를 얻었습니다.


그러나 addOneTo 메소드를 사용하여 1에서 5까지 5 배를 더하려면 어떻게해야할까요?
























1
2
3
4
5
6
7
8
9
10
11
12
// 5 + 1 + 1 + 1 + 1 + 1 = 10
addOneTo(5function(res1){
    addOneTo(res1, function(res2){
        addOneTo(res2, function(res3){
            addOneTo(res3, function(res4){
                addOneTo(res4, function(res5){
                    console.log(res5);
                });
            });
        });
    });
});
cs


이것이 콜백 지옥!

Promises

promises는 콜백 지옥을 해결할 수있는 좋은 방법입니다. 약속에서 우리는 결과와 콜백을 호출하는 대신 미래에 결과를 얻을 것이라고 약속합니다. 새로운 약속 기반의 addOneTo 메소드 살펴보기

1
2
3
4
5
6
7
8
9
10
11
const addOneTo = function(number){
    let result = number + 1;
    return new Promise(function(resolve, reject){
        resolve(result);
    });
}
// 5 + 1 = 6
addOneTo(5)
    .then(function(res){
        console.log(res);
    });
cs

promises 객체는 즉각 반환되지만 그 결과는  나중에 도착합니다. promises는 두개의 인수를 갖게되는데  resolve  와 reject입니다.
resolve우리는 결과가 있을 때 부르고 오류가있을 때 reject가 호출됩니다. 반환이 약속 객체는  then 와 catch 두 가지 방법이있습니다,
 then 은  resolve메서드를 통해 발생한 결과를 가져옵니다catch는 reject 메소드로 throw 된 에러를 가져옵니다. 
약속을 사용하여 비동기 호출을 동기 방식으로 연결할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 5 + 1 + 1 + 1 + 1 + 1 = 10
addOneTo(5)
    .then(function(res1){
        return addOneTo(res1);
    })
    .then(function(res2){
        return addOneTo(res2);
    })
    .then(function(res3){
        return addOneTo(res3);
    })
    .then(function(res4){
        return addOneTo(res4);
    })
    .then(function(res5){
        console.log(res5);
    })
cs



=> 더 이쁘게 만들어 보기!
1
2
3
4
5
6
addOneTo(5)
.then(addOneTo)
.then(addOneTo)
.then(addOneTo)
.then(addOneTo)
.then(console.log)
cs

Generators

promises가 잘 작동하지만, generators를 통해 더 간단하고 깨끗하게 만들수 있습니다.
generators는 *가 있는 함수입니다.
function *()로 붙여주면 됩니다.
generators는 일시 중단하거나 다시 시작하는 기능이 있습니다.
이 예제에서는 직접 generators를 다루지 않고 관련 라이브러리인 co를 사용하여 generator를 사용할것입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const co = require('co');
const addOneTo = function(number){
    let result = number + 1;
    return new Promise(function(resolve, reject){
        resolve(result);
    });
}
co(function *(){
    let res1 = yield addOneTo(5);
    let res2 = yield addOneTo(res1);
    let res3 = yield addOneTo(res2);
    let res4 = yield addOneTo(res3);
    let res5 = yield addOneTo(res4);
    return res5;
})
.then(function(result){
    console.log(result);
});
cs

여기에서는 promises와 generators를 함께 사용 하였습니다.

co library가 제공하는 generator 메소드로 function을 감쌌습니다.

여기서 yield 라는 새로운 키워드가 있는데. yield는 우리가 결과를 받았을때만 라이브러리를 재개합니다.

이 모든것은 비동기적으로 움직입니다.

이 코드도 또한 동기코드처럼 보이게 되었으며 이로인하 우리가 프로그램을 이해하기 수월하게 되고 나중에 확장할수 있게 되었습니다,.

 Async & Await

 Async & Await은 발전기의 다음 단계입니다. generators와 마찬가지로 promise를 활용합니다.
async로 비동기 호출을 선언하고, await 키워드로 결과를 기다리고 가져올수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const addOnTo = function(number){
    let result = number + 1;
    return new Promise(function(resolve, reject){
        resolve(result);
    });
}
async function main(){
    let res1 = await addOnTo(5);
    let res2 = await addOnTo(res1);
    let res3 = await addOnTo(res2);
    let res4 = await addOnTo(res3);
    let res5 = await addOnTo(res4);
    console.log(res5);
}
main();
cs
이 방법은 앞서 논의된 다른 모든 기술과 비교해서 관리가 쉽고 유지관리가 쉽습니다.



728x90
반응형
Comments