30
Flow Control in Node.js 송형주

Flow control in node.js

  • Upload
    iamhjoo-

  • View
    15.901

  • Download
    3

Embed Size (px)

DESCRIPTION

Node.js에 주요 이슈 중 하나인 Flow Control에 대해서 Octobersky.js 모임에서 발표한 자료

Citation preview

Page 1: Flow control in node.js

Flow Control in Node.js송형주

Page 2: Flow control in node.js

● 삼성전자 소프트웨어센터 Web Convergence Lab.

● 블로그

Inside.JS (http://www.nodejs-kr.org/insidejs)

Profile

Page 3: Flow control in node.js

var fs = require('fs') , path = './sync.txt'; var stats = fs.statSync(path);

if (stats == undefined) { // read the contents of this file var content = fs.readFileSync(__filename);} var code = content.toString();// write the content to sync.txtvar err = fs.writeFileSync(path, code);if(err) throw err;console.log('sync.txt created!'); console.log(‘Another Task’);

Synchronous Programming

Page 4: Flow control in node.js

var fs = require('fs') , path = './async.txt'; // check if async.txt existsfs.stat(path, function(err, stats) { if (stats == undefined) { // read the contents of this file fs.readFile(__filename, function(err, content) { var code = content.toString(); // write the content to async.txt fs.writeFile(path, code, function(err) { if (err) throw err; console.log('async.txt created!'); }); }); }}); console.log(‘Another Task’);

Asynchronous Programming

Page 5: Flow control in node.js

Node.js programming is not easy.var open = false; setTimeout(function () { open = true;}, 1000); while(!open) { // wait} console.log('opened!');

Page 6: Flow control in node.js

Nested Callback Problemasync1(function(input, result1) { async2(function(result2) { async3(function(result3) { async4(function(result4) { async5(function(output) { // do something with output }); }); }); });})

Page 7: Flow control in node.js

Flow Control Problem

for(var i = 1; i <= 1000; i++) { fs.readFile('./'+i+'.txt',

function() { // do something with the file } );} do_next_part();

Page 8: Flow control in node.js

Why Flow Control?

• Asynchronous Programming • Issues – Doing a bunch of things in a specific order – Knowing when task is done. – Nested Callback – Collecting result data

Page 9: Flow control in node.js

Flow Control Pattern

• Serial Execution• Parallel Execution• Limited Parallel Execution

Page 10: Flow control in node.js

Serial Execution

Start

Task1

Task3

Continue when tasks complete

Task2

Page 11: Flow control in node.js

Parallel Execution

Start

Task1 Task3

Continue When tasks complete

Task2

Page 12: Flow control in node.js

Flow Control Libraries

• Async – providing various control function• Step – simple and easy to use• Slide – used in the npm client code• Seq• Nue• …

Page 13: Flow control in node.js

Node.js Coding Conventions• Two kinds of functions : – Action Function : Take action – Callback Function : Get results • Action functions – last argument is always a callback function

• Callback functions – first argument is always an error or null.

Page 14: Flow control in node.js

Action Function

CallbackFunctionResult

(Action Function Developer) (Action Function User)

Page 15: Flow control in node.js

Action Function Example

function actor (some, args, cb) { // last argument is callback // optional args: if (!cb && typeof(args) === "function")

cb = args, args = []; // do something, and then: if (failed) cb(new Error("failed!")) else cb(null, optionalData)}

Page 16: Flow control in node.js

Action Function

CallbackFunctionResult

Action Function과 Callback Function 사이는 결과를 어떻게 넘길 지에 대한 인터페이스가 명확히 규정되어 한다.

Page 17: Flow control in node.js

Action Function Example// return true if a path is either// a symlink or a directory. function isLinkOrDir (path, cb) { fs.lstat(path, function (er, s) { if (er) return cb(er); return cb(null, s.isDirectory() || s.isSymbolicLink()); });} isLinkorDir

cbResultfs.lstat _cb

er, s er, result

Page 18: Flow control in node.js

Usecases : Parallel Execution

● I have a list of 10 files, and need to read all of them, and then continue when they're all done. 

● I have a dozen URLs, and need to fetch them all, and then continue when they're all done.

●I have 4 connected users, and need to send a message to all of them, and then continue when that's done.

Page 19: Flow control in node.js

function asyncMap (list, fn, cb_) { var n = list.length , results = [] , errState = null; function cb (er, data) { if (errState) return; if (er) return cb(errState = er); results.push(data); if (--n === 0) // 모든 리스트 처리 완료시

return cb_(null, results); } // action code list.forEach(function (l) { fn(l, cb); });}

Page 20: Flow control in node.js

asyncMap

listresult

fn cb

cb_

err, result

중간 결과 저장

err, data

Page 21: Flow control in node.js

Usecases : AsyncMapfunction writeFiles (files, what, cb) { asyncMap(files, function (f, cb_) { fs.writeFile(f,what,cb_); }, cb );} writeFiles([my,file,list], "foo", cb);

writeFiles

cb

err

asyncMap

files

cb_는 asyncMap의 내부 함수임

list

fn cb_

Page 22: Flow control in node.js

This implementation is fine if order doesn'tmatter, but what if it does?

Page 23: Flow control in node.js

function asyncMap(list, fn, cb_) { var n = list.length , results = [] , errState = null;

function cbGen (i) { return function cb(er, data) { if (errState) return; if (er) return cb(errState = er); results[i] = data; if (-- n === 0) return cb_(null, results); } } list.forEach(function (l, i) { fn(l, cbGen(i)); });}

Page 24: Flow control in node.js

usecase: Serial Execution

• I have to do a bunch of things, in order. Get db credentials out of a file, read the datafrom the db, write that data to another file. • If anything fails, do not continue.

Page 25: Flow control in node.js

function chain (things, cb) { (function LOOP (i, len) { if (i >= len) return cb(); things[i](function (er) { if (er) return cb(er); LOOP(i + 1, len) }) })(0, things.length)}

Page 26: Flow control in node.js

cb

chainLOOP,0

things[1]

LOOP, 3

things[0] LOOP,1

LOOP,2

things[2]

things

Page 27: Flow control in node.js

var fs = require('fs');var async = require('async'); var path = './async.txt';async.waterfall([

// check if async.txt existsfunction(cb) {

fs.stat(path, function(err, stats) { if (stats == undefined) cb(null); else console.log('async.txt exists'); });

},// read the contents of this filefunction(cb) {

fs.readFile(__filename, function(err, content) { var code = content.toString(); cb(null, code); });

},// write the content to async.txtfunction(code, cb) {

fs.writeFile(path, code, function(err) { if (err) throw err; console.log('async.txt created!'); });

}]);

Async Module Example

Page 28: Flow control in node.js

Step( function readSelf() { fs.readFile(__filename, 'utf8', this); }, function capitalize(err, text) { if (err) throw err; return text.toUpperCase(); }, function showIt(err, newText) { if (err) throw err; console.log(newText); });

Step Module Example

Page 29: Flow control in node.js

Step( // Loads two files in parallel function loadStuff() { fs.readFile(__filename, this.parallel()); fs.readFile("/etc/passwd", this.parallel()); }, // Show the result when done function showStuff(err, code, users) { if (err) throw err; console.log(code); console.log(users); })

Step Module Example