Object.observe()ã¨Node.jsã®ã¤ãã³ãã«ã¼ãã®é¢ä¿
1. ã¯ããã«
æè¿ Chrome 㧠Object.observe() ãããã©ã«ãã§æå¹ã«ãªãã¾ããã
ã³ããããã°ãè¦ãã°ãããã¾ããã2å revert ãããå¾ã®3度ç®ã®æ£ç´ã®ã³ãããã§ãã
確ãã« Object.observe() ã¯é常ã«å¼·åãªAPIã§ããã©ãES6ã®ä»æ§åè£ã®æ©è½ã«å ¥ã£ã¦ãã¾ãããï¼ES.harmony or ES7?) ã¡ãã£ã¨åã«å¤§å¹ ãªä»æ§è¦ç´ãããã£ãã®ã§ããããªè¦å´ãã¦ã¾ã§ããããã©ã«ãã§æå¹ã«ãããªãã¨ä¸æè°ã§ããã
ãããä»æ¥ AngularJS 2.0 ã®ãªãªã¼ã¹ãè¦ã¦åç¹ããã¾ãããPolymerã®MLã«ãæµãã¦ã¾ããã
Googleãããæ»ãã¦ã¾ããã¼ã
Object.observe()ã®æ©è½ã«ã¤ãã¦ã¯ä¸è¨è¨äºãåç §ã«ãã¦ãã ããã(ã¾ã js-nextããã®è¨äºã®ç´¹ä»ã ããã¤ããããã¨ããããã¾ããï¼
ä»æ§æ¹å®åã®å¤ããã®ã§ãããã¡ããç§ã®ã¨ã³ããªã¼ãè¼ãã¦ããã¾ãã
ããã§æ°ã«ãªãNodeã¨ã®é¢ä¿ã§ããããã©ã«ã㧠Object.observe()ã使ããã®ã¯ãææ°(breeding edge)çã®V8 3.25ãªã®ã§ãæ¨æ¥ç´¹ä»ãã Node(V8 3.24)ã§ã¯ãä¾ç¶ harmony ãªãã·ã§ã³ãå¿ è¦ã§ãããã ãã®ã¾ã¾ Node-v0.12 ã®ãªãªã¼ã¹ãé ããã¨ãã²ãã£ã¨ã㦠Node ã® V8 ã3.25ã«ã¢ãããã¼ãããããããã¾ãããã次㮠Node-v0.13(ããããã¦1.x?)ã§ã¯ç¢ºå®ã«å ¥ãã§ããããè¿ãå°æ¥ãNodeã§Object.observe() ãããã©ã«ãã§ä½¿ããã¨ãªãã¨ãããã¾ã§ã¨å ¨ãéãä¸çãç¾ããã®ã§ã¯ãªããã¨å¤¢ãã²ããããããã¦ãã¾ãã¾ãã
å人çã«ã¯ãã¾ã å ·ä½çã«å¤¢ã®ããã°ãã¨ãããããªä½¿ãæ¹ã¯èãããã¦ãã¾ããããNodeã§Object.observe()ã使ãã¨ããã®ã³ã¼ã«ããã¯ã£ã¦Nodeã®ã³ã¼ã«ããã¯ã¨ã©ãéããã ãããããã¨ãã©ãä¸ç·ãªãã ãããï¼ ã¨ãã£ãçåããµã¨ããã¦ãã¾ãããããæãã¨æ°ã«ãªã£ã¦æ°ã«ãªã£ã¦ä»æ¹ããªããææ ¢ã§ããã«ãã£ããæ¤è¨¼ãã¦ã¿ã¾ãããï¼å稿ã®ç· ãåãç´åã«ãã£ã¦ã¦ãããã ãããã»ã»ã»ã»ï¼
2. Node ã§ã¯ Object.observe() ã®ã³ã¼ã«ããã¯ã¯ã©ã®ã¿ã¤ãã³ã°å®è¡ãããï¼
V8ã®ææ°çã®å®è£ ãè¦ã¦ã¿ã㨠Object.observe() ã¯å é¨ã« Microtask Queue ãä¿æãã¦ãã¿ã¹ã¯ç®¡çããã¦ããããã§ããæ¨æ¥ç´¹ä»ãã Promise ãåãä»çµã¿ã¿ããã§ãã
Nodeã§æ±ãã³ã¼ã«ããã¯ã¯ãI/Oã³ã¼ã«ããã¯ãsetImmediateã0ç§ã® setTimeoutãprocess.nextTickãEventEmitterã¨ãã£ã¨5種é¡ãããã« Object.observeã®ã³ã¼ã«ããã¯ãObject.deliverChangeRecordsã«ããã³ã¼ã«ããã¯ã®2種é¡ã§åè¨7種é¡ããã¾ãã
EventEmitter 㨠Object.deliverChangeRecords ã¯åæçãªåä½ã ã¨äºæ³ãããã®ã§ï¼ã¤ã®EventEmitterã®éã« Object.deliverChangeRecords ãæã¿è¾¼ã¿ã¾ããçµæãã³ã¼ã«ããã¯ã®èµ·åé åºã表示ãããã¹ãã¹ã¯ãªããã以ä¸ã®æ§ã«ãã¾ããã
// Object.observe()ã¨Nodeã®ã³ã¼ã«ããã¯ã®å®è¡é ã確èªãããã¹ã var util = require('util'); var EventEmitter = require('events').EventEmitter; var fs = require('fs'); var order = 1; // Test Event Object function MyObj() {} util.inherits(MyObj, EventEmitter); var myobj = new MyObj(); // Event emitter callback myobj.on('myevent', function(msg) { console.log(order++, 'myevent msg: '+ msg +' emitted'); }); // Object.observe callback function callback(changeRecord) { console.log(order++, 'Object.observed:', changeRecord); } Object.observe(myobj, callback); // Start Testing fs.stat(__filename, function(stat) { console.log(order++, 'I/O callback(fs.stat)'); }); // At the last of event loop setImmediate(function() { console.log(order++, 'setImmediate called'); }); // Timer setTimeout(function() { console.log(order++, 'setTimeout 0sec called'); }, 0); // At the finish of JavaScript Runtime process.nextTick(function(){ console.log(order++, 'process.nextTick called'); }); myobj.hoge = 'deliverChanged'; myobj.emit('myevent', 'first event'); Object.deliverChangeRecords(callback); myobj.emit('myevent', 'second event'); myobj.hoge = 'foo';
ã§ãå®è¡çµæãããã§ãã
$ node --harmony test1.js 1 'myevent msg: first event emitted' 2 'Object.observed:' [ { type: 'add', object: { _events: [Object], hoge: 'deliverChanged' }, name: 'hoge' } ] 3 'myevent msg: second event emitted' 4 'process.nextTick called' 5 'Object.observed:' [ { type: 'update', object: { _events: [Object], hoge: 'foo' }, name: 'hoge', oldValue: 'deliverChanged' } ] 6 'setTimeout 0sec called' 7 'I/O callback(fs.stat)' 8 'setImmediate called'
çµæã表ã«ã¾ã¨ããã¨ãããªæãã§ãã
æ©è½ | è¨è¿°é | å®è¡é |
I/O callback(fs.stat) | 1 | 7 |
setImmediate | 2 | 8 |
setTimeout | 3 | 6 |
process.nextTick | 4 | 4 |
event emitter #1 | 5 | 1 |
Object.deliverChangeRecords | 6 | 2 |
event emitter #2 | 7 | 3 |
Observed Object property ã®å¤æ´ | 8 | 5 |
3. ã³ã¼ã«ããã¯èµ·åã®é çªã¨ã¤ãã³ãã«ã¼ãã®é¢ä¿
å人çã«äºæ³ããã®ã¯ Object.observe()ã®ã³ã¼ã«ããã¯ã®å¾ã« process.nextTickããªã¨æã£ãã®ã§ããéã£ã¦ã¾ãããã½ã¼ã¹ã確èªããã¨ãã¡ã¤ã³ã¢ã¸ã¥ã¼ã«ã®å¼ã³åºãã»å®è¡ã®æå¾ã« process.nextTick ãå¼ã³åºãã¦ãã¾ããã
https://github.com/joyent/node/blob/master/lib/module.js#L491-L492
ã¾ããObject.observe() ã®ã³ã¼ã«ããã¯ã¯ JS ã®å®è¡(Run)ã®æå¾ã«è¡ãããã®ã§ãã¡ã¤ã³ã¢ã¸ã¥ã¼ã«å®è¡å®äºå¾ã«èµ·åããã¾ãã
å³ã«ããã¨ãããªæãã§ãã
ã¾ã¨ããã¨ã
- EventEmitter 㨠Object.deliverChangeRecords() ã¯ãJSã®å®è¡ä¸ã«åæçã«ã³ã¼ã«ããã¯ãèµ·åãããã®ã§æ¸ããé çªã«ä¾åãã¾ãããã¹ãã¹ã¯ãªããã®åºåã¯ãã¤ãã³ãã«ã¼ãã®å³ã0:Loadãã§èµ·åãã¦ãã¾ãã
- process.nextTickã¯ã¡ã¤ã³ã¢ã¸ã¥ã¼ã«ã®èªã¿è¾¼ã¿ã»å®è¡ã®æå¾ãNodeã®ã³ã¼ã«ããã¯å¦çã®æå¾ã§å¼ã³åºããããããV8å®è¡ã®æå¾ã® Object.observe()ãããåã«èµ·åãããã
- ãã®ä»ã®ã³ã¼ã«ããã¯(Timer, SetImmediate, I/O)㯠libuv ã§å®è£ ãããã¤ãã³ãã«ã¼ãã®é çªã§èµ·åãããã
ã¨ãããã¨ã§ãã
ããããã£ããããã