Node.js async 모듈 사용해보기
2018-06-16 11:07:15

요즘에는 node.js에서 async/await, promise를 지원해줘서 주로 쓰지만 처음 입문하엿을 땐 지원이 안 되서 async 모듈을 주로 썻엇다. 지금도 종종 애용하는 중

순차적 처리

series, waterfall이 잇다.

series

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

const async = require('async');

const a = (cb) => {
setTimeout(() => {
cb(null, 1);
}, 4000);
};

const b = (cb) => {
setTimeout(() => {
cb(null, 2);
}, 1000);
};

const c = (cb) => {
setTimeout(() => {
cb(null, 3);
}, 2000);
};

async.series([a, b, c], (err, results) => {
if (err) {
console.log('err', err);
} else {
console.log('results', results);
}
});

함수의 실행 시간에 상관 업이 호출한 순서대로 실행 결과를 배열에 받는다.

함수의 콜백을 호출할 때 에러 처리를 할 경우 에러는 첫 인자에, 결과는 두 번째 인자에 넣어야 한다.

1
results [ 1, 2, 3 ]

waterfall

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

const async = require('async');

const a = (cb) => {
setTimeout(() => {
cb(null, 1);
}, 4000);
};

const b = (data, cb) => {
setTimeout(() => {
cb(null, data + 2);
}, 1000);
};

const c = (data, cb) => {
setTimeout(() => {
cb(null, data + 3);
}, 2000);
};

async.waterfall([a, b, c], (err, result) => {
if (err) {
console.log('err', err);
} else {
console.log('result', result);
}
});

waterfall도 함수의 실행 시간과 상관 업이 호출한 순서대로 실행을 하는데

series와 다른 점은 각 함수의 결과를 다음 함수에 파라미터로 넘길 수가 잇다.

마찬가지로 각 함수의 콜백의 첫 인자는 에러, 두 번째 인자는 넘길 데이터이다.

1
result 6

병렬 처리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const async = require('async');

const a = (cb) => {
setTimeout(() => {
cb(null, 1);
}, 2000);
};

const b = (cb) => {
setTimeout(() => {
cb(null, 2);
}, 3000);
};

async.parallel([a, b], (err, results) => {
if (err) {
console.log('err', err);
} else {
console.log('results', results);
}
});

동시에 호출한 함수들이 모두 완료되어야 호출한 순서대로 응답을 배열로 받는다.

1
results [ 1, 2 ]

반복

each와 eachSeries가 잇다.

each

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

const async = require('async');

const arr = [];

// eslint-disable-next-line no-plusplus
for (let i = 0; i < 10; i++) {
arr.push(i);
}

const a = (_param, cb) => {
const random = Math.floor(Math.random() * 3) + 1;
setTimeout(() => {
cb(_param);
}, random);
};

const results = [];

async.each(arr, (item, callback) => {
a(item, (data) => {
results.push(data);
callback();
});
}, (err) => {
if (err) {
console.log('err', err);
} else {
console.log('results', results);
}
});

each는 반복할 함수의 실행 시간에 따라 빨리 처리되는 순서대로 응답을 한다.

1
results [ 0, 6, 7, 8, 1, 4, 5, 2, 3, 9 ]

eachSeries

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

const async = require('async');

const arr = [];

// eslint-disable-next-line no-plusplus
for (let i = 0; i < 10; i++) {
arr.push(i);
}

const a = (_param, cb) => {
const random = Math.floor(Math.random() * 3) + 1;
setTimeout(() => {
cb(_param);
}, random);
};

const results = [];

async.eachSeries(arr, (item, callback) => {
a(item, (data) => {
results.push(data);
callback();
});
}, (err) => {
if (err) {
console.log('err', err);
} else {
console.log('results', results);
}
});

eachSeries는 무조건 반복할 함수의 실행 시간과 상관 업이 요청한 순서대로 응답을 한다.

단 그 만큼 데이터가 클 수록 실행 시간이 늘어난다.

1
results [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

여기 적은 건 내가 주로 쓰던 거들이고 이외에도 많은 기능등이 잇으므로 한 번씩 봐두도록 하자.

주의점

예로 series를 쓸 때 이러한 경우가 잇을 수 잇다.

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

const async = require('async');

let x = 100;

const a = (cb) => {
setTimeout(() => {
x += 10;
cb(null, 1);
}, 4000);
};

const b = (cb) => {
setTimeout(() => {
cb(new Error('ㅠㅠ'));
}, 1000);
};

const c = (cb) => {
setTimeout(() => {
cb(null, 3);
}, 2000);
};

async.series([a, b, c], (err, results) => {
if (err) {
console.log('err', err, 'x', x);
} else {
console.log('results', results);
}
});

첫 함수는 잘 동작햇지만 두번 째 함수에선 처리 중에 에러가 발생햇다고 치자.

이러면 실행 결과가 어떠케 될까?

1
2
3
4
5
6
err Error: ㅠㅠ
at Timeout.setTimeout [as _onTimeout] (/Volumes/Seagate Slim Drive/project/nodejs/async-example/error.js:15:8)
at ontimeout (timers.js:436:11)
at tryOnTimeout (timers.js:300:5)
at listOnTimeout (timers.js:263:5)
at Timer.processTimers (timers.js:223:10) x 110

그렇다. 첫 함수는 정상적으로 작동되엇기에 x는 증가가 되버렷다.

만약 각 함수마다 db에 뭔가 갱신을 하는 코드라면 좀 골치가 아파질수도 잇다.

예외 처리를 잘 생각하자.

Prev
2018-06-16 11:07:15
Next