talk-pitfalls - open index.html with a browser
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Title</title> | |
<meta charset="utf-8"> | |
<style> | |
@import url(https://fonts.googleapis.com/css?family=Yanone+Kaffeesatz); | |
@import url(https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic); | |
@import url(https://fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic); | |
body { font-family: 'Droid Serif'; } | |
h1, h2, h3 { | |
font-family: 'Yanone Kaffeesatz'; | |
font-weight: normal; | |
} | |
.remark-code, .remark-inline-code { font-family: 'Ubuntu Mono'; } | |
@media print { | |
.remark-slide-number { | |
/* hide slide numbers on print/PDF, viewer has its own */ | |
display: none; | |
} | |
} | |
@page { | |
size: 16cm 12cm; | |
} | |
</style> | |
</head> | |
<body> | |
<textarea id="source"> | |
class: center, middle | |
# Title: Node.js API Pitfalls | |
Who am I: | |
NodeOps Team Lead at StrongLoop@IBM | |
github: @sam-github | |
twitter: @octetcloud | |
instagram: ... sorry, no! | |
??? | |
rmg feedback: | |
- nextTick, don't mention max queue depth | |
- async.while, use next tick to block the event loop? | |
jordan feedback: | |
- make sure I know the slides back and forwards, it will make me confident, so do lots of prep | |
- be high-energy, be passionate, it improves the energy of the talk | |
- no intro, just dive in and go | |
--- | |
# Disclaimer ;-) | |
Doesn't necessarily reflect the views of Strongloop, IBM, or any of my Node.js | |
collaborators... | |
--- | |
# nextTick | |
```javascript | |
process.nextTick(function A() { | |
// Called ... | |
}); | |
``` | |
- [ ] in next tick of the event loop | |
- [ ] immediately after current stack returns | |
--- | |
# nextTick | |
```javascript | |
process.nextTick(function A() { | |
// Called ... | |
}); | |
``` | |
- [ ] in next tick of the event loop | |
- [x] immediately after current stack returns | |
--- | |
# setImmediate | |
```javascript | |
setImmediate(function A() { | |
// Called ... | |
}); | |
``` | |
- [ ] in next tick of the event loop | |
- [ ] immediately after current stack returns | |
--- | |
# setImmediate | |
```javascript | |
setImmediate(function A() { | |
// Called ... | |
}); | |
``` | |
- [x] in next tick of the event loop | |
- [ ] immediately after current stack returns | |
--- | |
# nextTick vs setImmediate | |
- `nextTick`: adds callback to queue to be called *immediately* | |
- `setImmediate`: adds callback to queue to be called *next tick* | |
--- | |
# worker.kill() | |
```javascript | |
var cluster = require('cluster'); | |
if (cluster.isMaster) { | |
cluster.fork() | |
.on('online', function() { | |
this.kill('SIGHUP'); | |
}) | |
.on('exit', function() { | |
console.log('Exit'); | |
}); | |
} else { | |
process.on('SIGHUP', function() { | |
console.log('Hup'); | |
}); | |
} | |
``` | |
??? | |
Walk through | |
--- | |
# worker.kill() | |
```javascript | |
var cluster = require('cluster'); | |
if (cluster.isMaster) { | |
cluster.fork() | |
.on('online', function() { | |
this.kill('SIGHUP'); | |
}) | |
.on('exit', function() { console.log('Exit'); }); | |
} else { | |
process.on('SIGHUP', function() { console.log('Hup'); }); | |
} | |
``` | |
- [ ] "Hup" | |
- [ ] "Exit" | |
- [ ] "Hup" and "Exit" | |
- [ ] No output | |
--- | |
# worker.kill() | |
```javascript | |
var cluster = require('cluster'); | |
if (cluster.isMaster) { | |
cluster.fork() | |
.on('online', function() { | |
this.kill('SIGHUP'); | |
}) | |
.on('exit', function() { console.log('Exit'); }); | |
} else { | |
process.on('SIGHUP', function() { console.log('Hup'); }); | |
} | |
``` | |
- [ ] "Hup" | |
- [x] "Exit" | |
- [ ] "Hup" and "Exit" | |
- [ ] No output | |
--- | |
# worker.kill() - what is it really? | |
```javascript | |
Worker.prototype.kill = function(signo) { | |
var proc = this.process; | |
this.once('disconnect', function() { | |
this.process.kill(signo || 'SIGTERM'); | |
}); | |
this.disconnect(); | |
}; | |
``` | |
- Use `worker.process.kill()` if you want to signal the worker | |
- Asymetric with `worker.send()`, `worker.on('message', ...)`, etc. | |
--- | |
# worker.suicide - kill the worker | |
```javascript | |
var cluster = require('cluster'); | |
if (cluster.isMaster) { | |
cluster.fork() | |
.on('online', function() { | |
this.kill('SIGTERM'); | |
}) | |
.on('exit', function() { | |
// this.suicide is .... | |
}); | |
} else { | |
} | |
``` | |
- [ ] true | |
- [ ] false | |
--- | |
# worker.suicide - kill the worker | |
```javascript | |
var cluster = require('cluster'); | |
if (cluster.isMaster) { | |
cluster.fork() | |
.on('online', function() { | |
this.kill('SIGTERM'); | |
}) | |
.on('exit', function() { | |
// this.suicide is .... | |
}); | |
} else { | |
} | |
``` | |
- [x] true | |
- [ ] false | |
--- | |
# worker.suicide - exit the worker | |
```javascript | |
var cluster = require('cluster'); | |
if (cluster.isMaster) { | |
cluster.fork() | |
.on('exit', function() { | |
// this.suicide is .... | |
}); | |
} else { | |
process.exit(0); | |
} | |
``` | |
- [ ] true | |
- [ ] false | |
--- | |
# worker.suicide - exit the worker | |
```javascript | |
var cluster = require('cluster'); | |
if (cluster.isMaster) { | |
cluster.fork() | |
.on('exit', function() { | |
// this.suicide is .... | |
}); | |
} else { | |
process.exit(0); | |
} | |
``` | |
- [ ] true | |
- [x] false | |
--- | |
# worker.suicide - what does it mean? | |
Actual meaning: "orderly exit" | |
- `worker.disconnect()` in parent (implicitly done by `worker.kill()`) | |
- `process.disconnect()` in worker | |
??? | |
problems with having "suicide" be the "good thing" | |
--- | |
# url.parse/format | |
```javascript | |
var url = require('url'); | |
var uri = url.parse('http://example.com:8080/path'); | |
uri.host = 'ibm.com'; | |
console.log(url.format(uri)); | |
``` | |
Prints <http://ibm.com:8080/path> ... | |
- [ ] yes | |
- [ ] no | |
--- | |
# url.parse/format | |
```javascript | |
var url = require('url'); | |
var uri = url.parse('http://example.com:8080/path'); | |
uri.host = 'ibm.com'; | |
console.log(url.format(uri)); | |
``` | |
Prints <http://ibm.com:8080/path> ... | |
- [ ] yes | |
- [x] no: <http://ibm.com/path> | |
--- | |
# url.parse/format | |
- `host` is "example.com:8080" | |
- `hostname` is "example.com" | |
--- | |
# url.parse/format | |
```javascript | |
var url = require('url'); | |
var uri = url.parse('http://example.com:8080/path'); | |
uri.hostname = 'ibm.com'; | |
console.log(url.format(uri)); | |
``` | |
Prints <http://ibm.com:8080/path> ... | |
- [ ] yes | |
- [ ] no | |
--- | |
# url.parse/format | |
```javascript | |
var url = require('url'); | |
var uri = url.parse('http://example.com:8080/path'); | |
uri.hostname = 'ibm.com'; | |
console.log(url.format(uri)); | |
``` | |
Prints <http://ibm.com:8080/path> ... | |
- [ ] yes | |
- [x] no: <http://example.com:8080/path> | |
--- | |
# url.parse/format | |
- `hostname` and `port` are ignored if `host` is present... | |
--- | |
# url.parse/format | |
```javascript | |
var url = require('url'); | |
var uri = url.parse('http://example.com:8080/path'); | |
delete uri.host; | |
uri.hostname = 'ibm.com'; | |
console.log(url.format(uri)); | |
``` | |
- <http://ibm.com:8080/path>, finally! | |
--- | |
# url.parse/format | |
- parse: "http://example:8080": | |
- `port` is 8080 | |
- `host` is "example:8080"... why not `hostport`? | |
- `hostname` is "example"... why not `host`? | |
- format: `hostname` and `port` are ignored if `host` is present | |
- shouldn't they be prefered over `host` if present? | |
--- | |
# path.parse/format | |
```javascript | |
var path = require('path'); | |
var bits = path.parse('some/dir/index.txt'); | |
// has: .name, .ext | |
bits.ext = '.html'; | |
console.log(path.format(bits)); | |
``` | |
Logs `some/dir/index.html`... | |
- [ ] yes | |
- [ ] no | |
--- | |
# path.parse/format | |
```javascript | |
var path = require('path'); | |
var bits = path.parse('some/dir/index.txt'); | |
bits.ext = '.html'; | |
console.log(path.format(bits)); | |
``` | |
Logs `some/dir/index.html`... | |
- [ ] yes | |
- [x] no: `some/dir/index.txt` | |
--- | |
# path.parse/format | |
Its probably like `url`... | |
```javascript | |
var path = require('path'); | |
var bits = path.parse('some/dir/index.txt'); | |
console.log(bits.base); // > index.txt | |
delete bits.base | |
bits.ext = '.html'; | |
console.log(path.format(bits)); | |
``` | |
Logs `some/dir/index.html`... | |
- [ ] yes | |
- [ ] no | |
--- | |
# path.parse/format | |
```javascript | |
var path = require('path'); | |
var bits = path.parse('some/dir/index.txt'); | |
console.log(bits.base); // > index.txt | |
delete bits.base | |
bits.ext = '.html'; | |
console.log(path.format(bits)); | |
``` | |
Logs `some/dir/index.html`... | |
- [ ] yes | |
- [x] no: `some/dir/` | |
--- | |
# path.parse/format | |
Its just completely different, format _always_ ignores `name` and `ext`. | |
Correct: | |
```javascript | |
var path = require('path'); | |
var bits = path.parse('some/dir/index.txt'); | |
bits.base = bits.name + '.html'; | |
console.log(path.format(bits)); // > some/dir/index.html | |
``` | |
--- | |
# streams v1, 2, 3 | |
From <https://nodejs.org/api/stream.html#stream_class_stream_readable>: | |
> Note that, for backwards compatibility reasons, removing 'data' event | |
handlers will not automatically pause the stream. Also, if there are piped | |
destinations, then calling pause() will not guarantee that the stream will | |
remain paused once those destinations drain and ask for more data. | |
--- | |
# streams v1, 2, 3 | |
From <https://nodejs.org/api/stream.html#stream_class_stream_readable>: | |
> Note that, for backwards compatibility reasons, removing 'data' event | |
handlers will not automatically pause the stream. Also, if there are piped | |
destinations, then calling pause() will not guarantee that the stream will | |
remain paused once those destinations drain and ask for more data. | |
_When can we delete backwards compat to v0.8?_ | |
--- | |
# Question | |
What kind of node do you want: a good one? or a (mostly) v0.8 compatible one? | |
@octetcloud As of right now, 30.4% of registered npm accounts are less | |
than 6 months old. | |
- Laurie Voss (@seldo), NPM, Nov. 28, 2015 | |
--- | |
# Answer | |
Its yours (and a lot of other people's) Node.js, speak out: | |
- github, twitter, etc.. | |
- Be tolerant (or intolerant) of breakages, but what you say will effect | |
what happens. | |
--- | |
# Feedback: | |
- github: @sam-github | |
- twitter: @octetcloud | |
- talk source: <https://gist.github.com/sam-github/4c5c019b92cf95fb6571>, | |
or <https://goo.gl/2RWpqE> | |
</textarea> | |
<script src="https://gnab.github.io/remark/downloads/remark-latest.min.js"> | |
</script> | |
<script> | |
var slideshow = remark.create(); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
process.nextTick(function A() { | |
process.nextTick(function B() { | |
// Called in next tick, or immediately after A returns? | |
}); | |
}); | |
// Called immediately |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var path = require('path'); | |
var bits = path.parse('some/dir/index.txt'); | |
bits.ext = '.html'; | |
console.log(path.format(bits)); // some/dir/index.txt | |
var path = require('path'); | |
var bits = path.parse('some/dir/index.txt'); | |
console.log(bits.base); // index.txt | |
delete bits.base | |
bits.ext = '.html'; | |
console.log(path.format(bits)); // some/dir/ | |
var path = require('path'); | |
var bits = path.parse('some/dir/index.txt'); | |
bits.base = bits.name + '.html'; | |
console.log(path.format(bits)); // some/dir/index.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
setImmediate(function A() { | |
setImmediate(function B() { | |
// Called in next tick, or immediately after A returns? | |
}); | |
}); | |
// Called in the next tick |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var dgram = require('dgram'); | |
var sock = dgram.createSocket('udp4'); | |
var mesg = '<34>Oct 11 22:14:15 mymachine'; | |
//sock.send(mesg, 514, 'localhost'); | |
// TypeError: First argument must be a buffer object. | |
// No other network APIs require Buffers (to my knowledge) | |
var dgram = require('dgram'); | |
var sock = dgram.createSocket('udp4'); | |
var mesg = Buffer('<34>Oct 11 22:14:15 mymachine'); | |
//sock.send(mesg, 514, 'localhost'); | |
// RangeError: Offset into buffer too large | |
var dgram = require('dgram'); | |
var sock = dgram.createSocket('udp4'); | |
var mesg = Buffer('<34>Oct 11 22:14:15 mymachine'); | |
sock.send(mesg, 0, mesg.length, 514, 'localhost'); | |
// yeah! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var url = require('url'); | |
var uri = url.parse('http://example.com:8080/path'); | |
uri.host = 'ibm.com'; | |
console.log(url.format(uri)); | |
// replaces the host and port | |
var url = require('url'); | |
var uri = url.parse('http://example.com:8080/path'); | |
uri.hostname = 'ibm.com'; | |
console.log(url.format(uri)); | |
// replaces nothing | |
var url = require('url'); | |
var uri = url.parse('http://example.com:8080/path'); | |
delete uri.host; | |
uri.hostname = 'ibm.com'; | |
console.log(url.format(uri)); | |
// worked |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var cluster = require('cluster'); | |
if (cluster.isMaster) { | |
cluster.fork() | |
.on('online', function() { | |
this.kill('SIGHUP'); | |
}) | |
.on('exit', function(code, signame) { | |
console.log('Exit'); | |
}); | |
} else { | |
process.on('SIGHUP', function() { | |
console.log('Hup'); | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var cluster = require('cluster'); | |
if (cluster.isMaster) { | |
cluster.fork() | |
.on('online', function() { | |
this.kill('SIGHUP'); | |
}) | |
.on('exit', function(code, signame) { | |
// FIXME why does it say it exited with SIGHUP? This is uv cacheing the | |
// signo, right? strace this | |
console.log('Exit with:', signame || code); | |
}); | |
} else { | |
process.on('SIGHUP', function() { | |
console.log('Hup, hup!'); | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var cluster = require('cluster'); | |
if (cluster.isMaster) { | |
cluster.fork() | |
.on('online', function() { | |
this.kill('SIGTERM'); | |
}) | |
.on('exit', function(code, signame) { | |
console.log('Exit with:', signame || code); | |
console.log('Suicide?', this.suicide); | |
}); | |
} else { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var cluster = require('cluster'); | |
if (cluster.isMaster) { | |
cluster.fork() | |
.on('exit', function(code, signame) { | |
console.log('Exit with:', signame || code); | |
console.log('Suicide?', this.suicide); | |
}); | |
} else { | |
process.exit(0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# dgram.send() | |
```javascript | |
var dgram = require('dgram'); | |
var sock = dgram.createSocket('udp4'); | |
var mesg = '<34>Oct 11 22:14:15 mymachine.samtu.com got lost in the cloud'; | |
sock.send(mesg, 514, 'localhost'); | |
``` | |
Look OK? | |
--- | |
# dgram.send() | |
```javascript | |
var dgram = require('dgram'); | |
var sock = dgram.createSocket('udp4'); | |
var mesg = '<34>Oct 11 22:14:15 mymachine.samtu.com got lost in the cloud'; | |
sock.send(mesg, 514, 'localhost'); | |
// > TypeError: First argument must be a buffer object. | |
``` | |
No other network APIs _require_ Buffers (to my knowledge) | |
--- | |
# dgram.send() | |
```javascript | |
var dgram = require('dgram'); | |
var sock = dgram.createSocket('udp4'); | |
var mesg = Buffer('<34>Oct 11 22:14:15 mymachine.samtu.com got lost in the cloud'); | |
sock.send(mesg, 514, 'localhost'); | |
``` | |
Look OK now? | |
--- | |
# dgram.send() | |
```javascript | |
var dgram = require('dgram'); | |
var sock = dgram.createSocket('udp4'); | |
var mesg = Buffer('<34>Oct 11 22:14:15 mymachine.samtu.com got lost in the cloud'); | |
sock.send(mesg, 514, 'localhost'); | |
// > RangeError: Offset into buffer too large | |
``` | |
`dgram` has no defaults... have to specify everything! | |
--- | |
# dgram.send() | |
Correct: | |
```javascript | |
var dgram = require('dgram'); | |
var sock = dgram.createSocket('udp4'); | |
var mesg = Buffer('<34>Oct 11 22:14:15 mymachine.samtu.com got lost in the cloud'); | |
sock.send(mesg, 0, mesg.length, 514, 'localhost'); | |
``` | |
??? | |
Documented... but idiosyncratic | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment