Universal JS
- JavaScript/Node.jsは、同じ言語なのでClient/Server Sideでコードを共有可能
- Validationなど共有可能
- けれど各moduleのAPIの仕様は必ずしも一致しない
- 仕様がどこにあるか、を知ることが重要
Q. JavaScriptのTimer APIの仕様はどこにあるでしょう?
A. whatwg
- "setTimeout"と検索
- MDN/MSDNなどが上位にくるので開く
- 片方しかない場合は、vendorがそのAPIを独自実装している可能性
- vendorがspec決めてる?
- ex, MDNなら「仕様」とい
う欄があるのでそこのリンクを辿ると......
- ex, MDNなら「仕様」とい
-
whatwgが決めていた
- w3c/whatwgはDOM(html等も含む)の仕様を定義
- ただしvendorが従っている保証はない
- EcmaはJSのruntimeのみ定義
- w3c/whatwgはDOM(html等も含む)の仕様を定義
Q. JSとNode.jsのTimer APIとでは仕様に違いがありますか?
A. JSとNode.jsのTimer APIの違い
- returnの型
- JSはID(number)
- Node.jsはTimeout obj
- timeout.ref(), timeout.unref()という便利な関数がある
- setImmediate API
- 各種ベンダーの内、MSのみdraftを定義
- Node.jsも同時期に開発したがspecが全然違う
-
setTimeout(() => console.log('ok'), 0)
- Browserでは0msで実行
- Node.jsでは1ms後に実行
Q. JavaScriptのConsole APIの仕様はどこにあるでしょう?
A. draft段階(標準化されてない)
- https://github.com/DeveloperToolsWG/console-object/blob/master/api.md
- ブラウザによってconsole.log等で表示される内容や見せ方は異なる(ブラウザによって実装が違う)
Q. Node.jsとEcmaScriptとで、Errorの仕様に違いはありますか?
A. あります
Errorオブジェクトのプロパティの観点で違いをみてみる
-
ECMAScript 2015: Error の定義
- Error.prototype
- Error.prototype.constructor
- Error.prototype.message
- Error.prototype.name
- Error.prototype.toString()
-
Node独自の追加
- error.code
- error.errno
- error.syscall
- stack系はdocに書かれている通りv8独自の追加
-
ベンダー独自の拡張(非標準)
- Error.prototype.description (MS)
- Error.prototype.number (MS)
- Error.prototype.fileName (Mozilla)
- Error.prototype.lineNumber (Mozilla)
- Error.prototype.columnNumber (Mozilla)
- Error.prototype.stack (Mozilla/v8)
- Error.captureStackTrace (v8)
- Error.stackTraceLimit (v8)
Node.jsのmodule固有のError property
以前は記載がなかったので、Node.jsのdocにPRしました
https://github.com/nodejs/node/pull/10986
module | property |
---|---|
net/http(s) | error.address |
net/http(s) | error.port |
fs | error.path |
// with `path` property
$node -e "require('fs').readFile('a file that does not exist', (err, data) => { console.error(err); });"
{ Error: ENOENT: no such file or directory, open 'a file that does not exist'
at Error (native)
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: 'a file that does not exist' }
// with `address` and `port` property
$node -e "require('net').connect({port: 100}).on('error', (err) => { console.error(err); });"
{ Error: connect ECONNREFUSED 127.0.0.1:100
at Object.exports._errnoException (util.js:1022:11)
at exports._exceptionWithHostPort (util.js:1045:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1087:14)
code: 'ECONNREFUSED',
errno: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 100 }
// with `address` property (without `port` property)
$node -e "require('net').connect({host: 'localhost'}).on('error', (err) => { console.error(err); });"
{ Error: connect EADDRNOTAVAIL 127.0.0.1 - Local (0.0.0.0:54881)
at Object.exports._errnoException (util.js:1022:11)
at exports._exceptionWithHostPort (util.js:1045:20)
at connect (net.js:881:16)
at net.js:1010:7
at GetAddrInfoReqWrap.asyncCallback [as callback] (dns.js:62:16)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:81:10)
code: 'EADDRNOTAVAIL',
errno: 'EADDRNOTAVAIL',
syscall: 'connect',
address: '127.0.0.1' }