learning node book, chapter 5

22
CH 5. 제어 흐름, 비동기 패턴, 예외 처리 Learning Node 김지훈

Upload: ji-hun-kim

Post on 20-May-2015

2.084 views

Category:

Internet


5 download

TRANSCRIPT

Page 1: Learning Node Book, Chapter 5

CH 5. 제어 흐름, 비동기 패턴, 예외 처리Learning Node

김지훈

Page 2: Learning Node Book, Chapter 5

Promise

Node의 초기 비동기 구현

success와 error 두 개의 이벤트만 가짐

Page 3: Learning Node Book, Chapter 5

Promise

var File = require('file'); var promise = File.read('mydata.txt'); promise.addCallback(function (data) { // process data }); promise.addErrback(function (err) { // deal with error })

Page 4: Learning Node Book, Chapter 5

– Ryan Dahl -

‘promise대신 최종 인수 콜백을 사용하도록 하고, 보다 나은 추상화 계층을 구축하는 것은 사용자 라이브러리에

맡기도록 하겠다.’

Promise 의 제거Node 0.1.30

Page 5: Learning Node Book, Chapter 5

최종 인수 콜백

모든 비동기 메서드는 마지막 인수로 콜백 함수를 받음

콜백의 첫번째 인수는 항상 error 개체

Last Argument Callbacks

Page 6: Learning Node Book, Chapter 5

최종 인수 콜백 구현 예시var obj = function() { }; obj.prototype.doSomething = function(arg1, arg2_) {

var arg2 = typeof(arg2_) === 'string' ? arg2_ : null;

var callback_ = arguments[arguments.length - 1]; callback = (typeof(callback_) == 'function' ? callback_ : null); if (!arg2)

return callback(new Error('second argument missing or not string')); callback(arg1); } var test = new obj(); test.doSomething(‘test', ‘this’, function(err,value) {

if (err) throw err;

console.log(value);

});

Page 7: Learning Node Book, Chapter 5

최종 인수 콜백의 역할

마지막 인수가 함수임을 보증

오류가 발생한 경우 Node Error를 생성하여 반환

오류가 발생하지 않으면 메서드의 결과를 전달하여 콜백 호출

Page 8: Learning Node Book, Chapter 5

중첩 콜백!var fs = require('fs'); try { fs.readFile('./apples2.txt','utf8', function(err,data) { if (err) throw err; var adjData = data.replace(/[A|a]pple/g,'orange');

fs.writeFile('./oranges.txt', adjData,function(err) { if (err) throw err

}); }); } catch(err) { console.error(err);

}

Nested Callbacks

Page 9: Learning Node Book, Chapter 5

// get list of files fs.readdir('./data/', function(err, files) {

// for each file

files.forEach(function(name) {

// modify contents fs.readFile('./data/' + name,'utf8', function(err,data) {

if (err) throw err; var adjData = data.replace(/somecompany\.com/g,'burningbird.net');

// write to file fs.writeFile('./data/' + name, adjData, function(err) {

if (err) throw err;

// log write writeStream.write('changed ' + name + '\n', 'utf8', function(err) {

if(err) throw err;

});

});

});

});

}); 콜백 스파게티, 죽음의 피라미드 (Pyramid of Doom)

Page 10: Learning Node Book, Chapter 5

changed data1.txt

changed data3.txt

changed data5.txt

changed data2.txt

changed data4.txt

!changed data3.txt

changed data1.txt

changed data5.txt

changed data2.txt

changed data4.txt

!changed data1.txt

changed data3.txt

changed data5.txt

changed data4.txt

changed data2.txt

콜백이 호출되는 순서도 무작위

Page 11: Learning Node Book, Chapter 5

서드파티 모듈

Node는 기본적인 콜백 기능만 제공

보다 높은 추상화는 서드파티 모듈에 의존해야 함

Step, Async

Page 12: Learning Node Book, Chapter 5

Step

간단한 서드파티 비동기 모듈

실행할 함수 리스트를 넘겨주면 순차적으로 실행해줌

Page 13: Learning Node Book, Chapter 5

var fs = require('fs'), Step = require('step'); try { Step ( function readData() { // 비동기 함수 fs.readFile('./data/data1.txt', 'utf8', this); }, function modify(err, text) { // 동기 함수 if (err) throw err; return text.replace(/somecompany\.com/g,'burningbird.net'); }, function writeData(err, text) { // 비동기 함수 if (err) throw err; fs.writeFile('./data/data1.txt', text, this); } ); } catch(err) { console.error(err); }

콜백 대신에 this를 전달 첫 번째 함수를 제외한 모든 함수는 첫 번째 매개변수로 error를 요구 에러는 예외로 처리

Page 14: Learning Node Book, Chapter 5

…생략… try { Step ( function readDir() { fs.readdir(_dir, this); }, function readFile(err, results) { if (err) throw err; files = results; var group = this.group(); results.forEach(function(name) { fs.readFile(_dir + name, 'utf8', group()); }); }, function writeAll(err, data) { if (err) throw err; for (var i = 0; i < files.length; i++) { var adjdata = data[i].replace(/somecompany\.com/g,'burningbird.net'); fs.writeFile(_dir + files[i], adjdata, 'utf8',this); } } ); } catch(err) { console.log(err); } ! 결과가 배열로 그룹화 되어 전달됨

Page 15: Learning Node Book, Chapter 5

병렬로 실행하기var fs = require('fs'), Step = require('step'), files; try { Step ( function readFiles() { fs.readFile('./data/data1.txt', 'utf8',this.parallel()); fs.readFile('./data/data2.txt', 'utf8',this.parallel()); fs.readFile('./data/data3.txt', 'utf8',this.parallel()); }, function writeFiles(err, data1, data2, data3) { if (err) throw err; data1 = data1.replace(/somecompany\.com/g,'burningbird.net'); data2 = data2.replace(/somecompany\.com/g,'burningbird.net'); data3 = data3.replace(/somecompany\.com/g,'burningbird.net'); fs.writeFile('./data/data1.txt', data1, 'utf8',this.parallel()); fs.writeFile('./data/data2.txt', data2, 'utf8', this.parallel()); fs.writeFile('./data/data3.txt', data3, 'utf8', this.parallel()); } ); } catch(err) { console.log(err); }

this.parallel()이 각 함수의 순서를 보장

Page 16: Learning Node Book, Chapter 5

Async

더 다양한 기능을 제공

기존 콜백구조와 매우 유사한 코드 스타일

Page 17: Learning Node Book, Chapter 5

var fs = require('fs'), async = require('async'); try { async.waterfall([ function readData(callback) { fs.readFile('./data/data1.txt', 'utf8', function(err, data){ callback(err,data); }); }, function modify(text, callback) { var adjdata=text.replace(/somecompany\.com/g,'burningbird.net'); callback(null, adjdata); }, function writeData(text, callback) { fs.writeFile('./data/data1.txt', text, function(err) { callback(err,text); }); } ], function (err, result) {//에러 발생시 처리를 중단하고 완료 콜백 호출 if (err) throw err; console.log(result); }); } catch(err) { console.log(err); }

Page 18: Learning Node Book, Chapter 5

async.waterfall

……

function readData(stats, file, callback) {

if (stats.isFile())

fs.readFile(_dir + file, 'utf8', function(err, data){

callback(err,file,data);

});

},

function modify(file, text, callback) {

var adjdata=text.replace(/somecompany\.com/g,'burningbird.net');

callback(null, file, adjdata);

},

……

async.waterfall([작업 함수 배열, …], 완료 콜백);

파라메터 전달 흐름

callback의 첫번째 인자는 error개체, 각 함수의 마지막 인자는 callback개체

Page 19: Learning Node Book, Chapter 5

async.parallelasync.parallel({

작업 이름 : 작업 함수,

… 반복 …

}, 완료 콜백);

넘겨준 작업 함수들을 모두 동시에 실행

모든 함수의 동작이 끝나길 기다렸다가 완료 콜백 호출

Page 20: Learning Node Book, Chapter 5

var fs = require('fs'), async = require('async');!

try { !

! async.parallel({!

! ! data1 : function (callback) {!

! ! ! fs.readFile('./data/data1.txt', 'utf8', function(err, data){!

! ! ! ! callback(err,data); !

! ! ! });!

! ! },! ! data2 : function (callback) {!

! ! ! fs.readFile('./data/data2.txt', 'utf8', function(err, data){ !

! ! ! ! callback(err,data);!

! ! ! });!

! ! },!

! ! data3 : function readData3(callback) { !

! ! ! fs.readFile('./data/data3.txt', 'utf8', function(err, data){!

! ! ! ! callback(err,data); !

! ! ! });!

! ! },!

! }, function (err, result) { // 완료 콜백!! ! if (err) throw err;!

! ! console.log(result); !

! });!

} catch(err) {!

! console.log(err); !

}

Page 21: Learning Node Book, Chapter 5

입력

data1.txt : apple

data2.txt : oranges

data3.txt : peaches

!

결과

{ data1: ‘apples\n’, data2: 'oranges\n', data3: 'peaches\n' }

{ 작업명 : 각 작업별 결과, … }

Page 22: Learning Node Book, Chapter 5

Node 스타일동기보다는 비동기 함수를 사용

2칸 들여쓰기 사용

세미콜론을 사용 / 사용하지 마라

작은 따옴표를 사용

여러 변수 선언시 단일 var 키워드 사용 / 여러 var 키워드 사용

상수는 모두 대문자

변수는 camel case

완전 항등 연산자(===) 사용

함수에 이름 붙이기

라인길이 80자 이하

중괄호는 중괄호를 필요로 하는 것과 같은 줄에서 시작