Você não conhece
William Grasel
@willgmbr
github.com/willgm
vivareal.com.br/empresa/carreira/
Arquitetura não bloqueante
Callbacks??
System.out.println("Step: 1");
System.out.println("Step: 2");
Thread.sleep(1000);
System.out.println("Step: 3");
console.log('Step: 1');
setTimeout(function () {
console.log('Step: 3');
}, 1000)
console.log('Step: 2');
Bloqueando seu NodeJS
for (let i = 1; i<1000000000; i++) {
// Vai levar 100 ~ 1000ms
}
const fs = require('fs');
const contents = fs.readFileSync('myfile.txt','utf8');
console.log('Hello Ruby', contents);
const fs = require('fs');
fs.readFile('myfile.txt','utf8', (err,contents) => {
console.log('Hello NodeJS', contents);
});
Window??
- global
- global.__filename
- global.__dirname
- global.process
Process attributes
- process.pid
- process.versions
- process.argv
- process.env
Process methods
- process.uptime()
- process.memoryUsage()
- process.cwd()
- process.exit()
- process.on()
CommonJS
const hello = require('world');
const hello = require('world');
exports.foo = function bar() {};
const hello = require('world');
exports.foo = function bar() {};
module.exports = { myObj: 123 };
const hello = require('world');
exports.foo = function bar() {};
module.exports = { myObj: 123 };
global.module.exports = {}
global.module
- module.exports
- module.filename
- module.id
Callback Hell =/
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})
Promises?
remotedb.allDocs({
include_docs: true,
attachments: true
}).then(function (result) {
var docs = result.rows;
docs.forEach(function(element) {
localdb.put(element.doc).then(function(response) {
console.log("Pulled doc with id ", element.doc._id);
}).catch(function (err) {
if (err.status == 409) {
localdb.get(element.doc._id).then(function (resp) {
localdb.remove(resp._id, resp._rev).then(function (resp) {
// Lá vamos nós de novo....
Vertical é melhor
remotedb.allDocs(...)
.then( resultOfAllDocs => localdb.put(...) )
.then( resultOfPut => localdb.get(...) )
.then( resultOfGet => localdb.put(...) );
Múltiplas promises
// Bora remover todas as linhas de um documento:
db.allDocs({include_docs: true})
.then( result => {
result.rows.forEach( row => {
db.remove(row.doc);
});
}).then(() => {
// Terminou??
});
// Bora remover todas as linhas de um documento:
db.allDocs({include_docs: true})
.then( result => {
return Promise.all(result.rows.map( row => {
return db.remove(row.doc);
}));
}).then( arrayDeResultados => {
// Agora sim todas as linhas foram removidas!
});
Caça fantasmas
minhaPromise().then(() => {
throw new Error('Oooops!');
}).catch( err => {
console.log(err);
});
Event Emitter
const events = require("events");
const emitter = new events.EventEmitter();
emitter.on("knock", () => {
console.log("Who's there?");
})
emitter.on("knock", () => {
console.log("Go away!");
})
emitter.emit("knock");
const { EventEmitter } = require('events');
class MyObject extend EventEmitter {
foo() {
this.emit('bar');
}
}
const hello = new MyObject;
hello.on('bar', () => console.log('wow'))
hello.foo();
Outros métodos
- emitter.listeners(eventName)
- emitter.once(eventName, listener)
- emitter.removeListener(eventName, listener)
Streams
- Readable: apenas leitura
- Writable: apenas escrita
- Duplex: leitura e escrita de entrada e saída diferente
- Transform: leitura e escrita de uma mesma entrada e saída
Node S2 Streams
- HTTP requests e responses
- Padrões de input/output
- Leitura e escrita de arquivos
Streams de Leitura
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', chunk => {
console.log('chunk: ', chunk)
});
process.stdin.on('end', () => {
console.log('--- END ---')
});
Streams de Escrita
const myStream = getWritableStreamSomehow();
myStream.write('some data');
myStream.write('some more data');
myStream.on('error', err => console.log('eita', err));
myStream.end('done writing data');
Pipes
const read = fs.createReadStream('file.txt');
const gzip = zlib.createGzip();
const write = fs.createWriteStream('file.txt.gz');
read.pipe(gzip).pipe(write);
process.stdin.on('data',
chunk => process.stdout.write(chunk)
);
process.stdin.pipe(process.stdout);
HTTP Streams
app.get('/get-image', (req, res) => {
fs.readFile('/large/image/path', (error, data) => {
res.end(data);
});
});
app.get('/get-image', (req, res) => {
fs.readFile('/large/image/path', (error, data) => {
res.end(data);
});
});
app.get('/stream', (req, res) => {
const stream = fs.createReadStream('/large/image/path');
stream.pipe(res);
});
Reactive Extensions
> npm install rx-node
const RxNode = require('rx-node');
RxNode.fromReadableStream(process.stdin)
.merge(anotherStream)
.map(data => (foo: 'bar', data))
.subscribe(data => console.log(data));
Clusters
const http = require('http');
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
const http = require('http');
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
for (var i = 0; i < numCPUs; i++)
cluster.fork();
} else {
const http = require('http');
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
for (var i = 0; i < numCPUs; i++)
cluster.fork();
} else {
http.createServer((req, res) => {
res.writeHead(200);
res.end(`hello world! ${process.pid}`);
}).listen(8000);
}
Load Balancing
Child Process
- Fork
- Spawn
- Exec
process.fork
const fs = require('fs');
const process = require('child_process');
const p = process.fork('program.js');
p.stdout.on('data', data => {
console.log('stdout: ' + data);
});
process.spawn
const fs = require('fs');
const process = require('child_process');
const p = process.spawn('ls', ['-lh', '/usr']);
p.stdout.on('data', data => {
console.log('stdout: ' + data);
});
process.exec
const fs = require('fs');
const process = require('child_process');
process.exec('cat *.js bad_file', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
Referências
Perguntas?
Obrigado! =)
@willgmbr
github.com/willgm
Copy of Você não conhece NodeJS
By neuber sousa
Copy of Você não conhece NodeJS
- 987