티스토리 뷰

node.js는 콜백에 콜백에 콜백을 찾는다는 얘기를 들은적이 있습니다.


저는 macOS와 iOS를 병행해가면서 개발하고 있는데 Callback 메서드를 아예 이용하지 않는 것은 아닙니다.


하지만 연속으로 계속되는 Callback 메서드를 사용하지는 않았는데요, 이번에 node.js를 배우면서 머리가 지끈지끈 아팠습니다.


연속으로 쏟아지는 Callback 메서드에 코드가 잘 보이지 않고 이해가 잘 되지 않는 자신에게 화도나고... 강의를 보고나서 하루는 정신을 못차렸습니다.


task1(arg1, (error, result) => { 
    task2(arg2, result, (error, result2) => {
        task3(arg3, result2, (error, result3) => {
            // 복잡해!
        });
    });
});


그런데 몇일 지나고나서 천천히 생각하면서 작업을 해보니 눈에 보이기 시작해서 연달아서 쭉 코드를 작성해보았습니다.


강의를 보면서 정리한 내용을 블로그에도 남깁니다.


Callback 지옥에서 벗어나는 방법으로 3가지를 제시합니다.


1. Async


npm을 이용해서 간단하게 설치해서 사용할 수 있습니다.

$ npm install async


Async 중에는 series, waterfall, parallel 방법이 있습니다. 이중에서 series방법을 이용했습니다.

function taskA(callback) {
    setTimeout(() => {
        callback(null, 'Result');
    }, 1000);
}

function taskB(callback) {
    setTimeout(() => {
        callback(null, 'Result');
    }, 2000);
}

function taskC(callback) {
    setTimeout(() => {
        callback(null, 'Result');
    }, 3000);
}
// 위, 아래 방법이 같은 결과를 보여줍니다. (물론 출력 횟수가 다르긴 합니다.)
const async = require('async');
async.series([
    (callback) => { console.log('TaskA'); callback(null, 'ResultA'); },
    (callback) => { console.log('TaskB'); callback(null, 'ResultB'); },
    (callback) => { console.log('TaskC'); callback(null, 'ResultC'); }
])

async.series([taskA, taskB, taskC],
    (err, results) => {
        console.log('Task A, B, C', reuslts);
    }
);


2. Promise

JavaScript ES6에서 모듈로 정식 포함되어 별도 설치가 필요하지 않은 모듈입니다.

웹에서 사용할 때는 브라우저별로 작동하지 않을 수 있으니 확인 작업이 필요합니다.


Promise의 상태는 Pending (동작 완료 전), fulfilled (동작 성공), rejected (동작 실패) 로 나누어집니다.

function task(arg) {
    return new Promise( (resolve, reject) => {
        // 비동기 동작
        if ( success )
             resolve('Success');
        else
             reject('Error');
       });
}


위처럼 비동기 동작을 함수로 작성을 마쳤다면, 이제 사용해 볼 차례입니다.

task1().then( task1Result => { 
    return task2(task1Result);
 }).then(task2Result => {
     return task3(task2Result);
}).then(task3Result => {
    console.log('All Tasks Done with', task3Result);
}).catch(error => { 
    console.log(error);
});

위와 같이 체인 형식으로 작성할 경우 error를 처리하지 않으면 오류메세지가 발생하니 주의해야합니다.

(node:40789) UnhandledPromiseRejectionWarning: Taskinjung result
warning.js:18
(node:40789) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
warning.js:18
(node:40789) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.


3. Await-Async

JavaScript ES7, node.js 7.6이상에서 지원되는 모듈입니다.

Promise 기반의 태스크를 동기식 API 처럼 사용할 수 있습니다.

Promise 모듈보다 더 늦게 나왔기 때문에 웹 브라우저에서는 작동 안하는 경우가 있으니 확인이 필요합니다.


Promise 기반의 비동기 태스트를 사용하는 방법입니다.

function asyncTask() {
     return new Promise( (resolve, reject) => {
// 비동기 동작 코드 });
}

//  Promise로 실행
asyncTask().then( onfulfilled, onRejected );
//  async/await로 실행
async function doIt() {
    let result = await asyncTask();
} 
doIt();


여기서, 에러처리까지 하고싶다면 아래와 같이 사용하면 됩니다.

async function doIt() { try {
         let result = await asyncTask();
         console.log('Task Done with', result);
     } catch (error) {
         console.log('Task Failure', error);
     }
} 
doIt();


여러 비동기 태스크를 이용하려면 아래와 같이 사용하면 됩니다.

async function doIt() { try {
    let r1 = await task1();
    let r2 = await task2(r1); 
    let result = await task3(r2);
} catch (error) {   
    console.log('Task Failure', error);
}}


노트 개념으로 적다보니 정리되어 보이지는 않지만 혹시나 도움이 될까 싶어 글로 남깁니다.


어느새 새로운 일주일이 시작 되었네요.


저번주도 고생 많으셨고 이번주도 다같이 화이팅하는 한주가 되었으면 좋겠습니다. 고생하셨습니다.


'Develop > Node.js' 카테고리의 다른 글

[node.js] session 관련 모듈  (1) 2018.06.24
[node.js] 'socket.io' module  (0) 2018.06.17
[node.js] transmission  (0) 2018.05.13
[node.js] 'url' module  (0) 2018.03.13
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
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