Reaktorã¯ãããã°ã§ãåŸæ¥å¡Petka AntonovïŒPetka AntonovïŒã«ãã£ãŠäœæãããBluebird Promisesã©ã€ãã©ãªã§äœ¿çšãããJavaScriptã³ãŒãæé©åã®ååãšäŸãå ±æããŸããã
Bluebirdã¯ã人æ°ã®ããJavaScript Promiseã©ã€ãã©ãªã§ãã 2013幎ã«æåã«æ°ã¥ãããã®ã¯ãåæ§ã®ããããã£ã»ãããåããä»ã®Promiseså®è£ ãæ倧100åäžåãããšãå€æãããšãã§ãã JavaScriptã®åºæ¬çãªæé©åååã®ããã€ããäžè²«ããŠé©çšããŠãããããBluebirdã¯éåžžã«é«éã§ãã ãã®èšäºã§ã¯ãBluebirdã®æé©åã«äœ¿çšããã3ã€ã®æãéèŠãªååã«ã€ããŠè©³ãã説æããŸãã
1.æ©èœã®äœæãæå°éã«æãã
ãªããžã§ã¯ãã®äœæãç¹ã«é¢æ°ãªããžã§ã¯ãã®äœæïŒ ç¿»èš³è æ³šïŒ ãã¹ãŠã®é¢æ°ã¯ãªããžã§ã¯ãã§ã ïŒ ã¯ã倧éã®å éšããŒã¿ã䜿çšããå¿ èŠããããããããã©ãŒãã³ã¹ã®ç¹ã§éåžžã«ã³ã¹ããããããŸãã å®éã®JavaScriptå®è£ ã«ã¯ã¬ããŒãžã³ã¬ã¯ã¿ãŒãå«ãŸããŠããŸããã€ãŸããäœæããããªããžã§ã¯ãã¯ã¡ã¢ãªå ã«çãŸãããšã¯ãããŸãããã¬ããŒãžã³ã¬ã¯ã¿ãŒã¯æªäœ¿çšã®ãªããžã§ã¯ããåžžã«æ€çŽ¢ããŠãå æããŠããã¡ã¢ãªã解æŸããŸãã JavaScriptã§äœ¿çšããã¡ã¢ãªãå€ãã»ã©ãã¬ããŒãžã³ã¬ã¯ã·ã§ã³ã«ãããCPUãå€ããªããã³ãŒãèªäœãæ©èœããããã«æ®ãããéãå°ãªããªããŸãã JavaScriptã§ã¯ãé¢æ°ã¯ãã¡ãŒã¹ãã¯ã©ã¹ãªããžã§ã¯ãã§ã ã ããã¯ãä»ã®ãªããžã§ã¯ããšåãæ©èœãšããããã£ãæã£ãŠããããšãæå³ããŸãã å¥ã®é¢æ°ã®å®£èšãå«ãé¢æ°ãããå Žåãå ã®é¢æ°ãåŒã³åºããã³ã«ãåãããšãè¡ãæ°ããäžæã®é¢æ°ãäœæãããŸãã ç°¡åãªäŸãèããŠã¿ãŸãããã
function trim(string) { function trimStart(string) { return string.replace(/^\s+/g, ""); } function trimEnd(string) { return string.replace(/\s+$/g, ""); } return trimEnd(trimStart(string)) }
trim
ãåŒã³åºããããã³ã«ã trimStart
ãštrimEnd
ãè¡šã2ã€ã®é¢æ°ãªããžã§ã¯ããäœæãããŸãã ãã ããããããã£ã®å²ãåœãŠãªã©ã®ãªããžã§ã¯ãåºæã®åäœãå€æ°ã®éå
ã䜿çšããªãããããããã¯å¿
èŠãããŸããã ãããã䜿çšãããå¯äžã®çç±ã¯ãå«ãŸããã³ãŒãã®æ©èœã®ããã§ãã
ãã®äŸã¯ç°¡åã«æé©åã§ããŸã-é¢æ°ãtrim
ããåãåºãã ãã§ãã ãã®äŸã¯ã¢ãžã¥ãŒã«ã«å«ãŸããŠãããã¢ãžã¥ãŒã«ã¯ããã°ã©ã ã«äžåºŠããŒãããããããé¢æ°ã®å Žåãè¡šçŸã¯1ã€ã ãã§ãã
function trimStart(string) { return string.replace(/^\s+/g, ""); } function trimEnd(string) { return string.replace(/\s+$/g, ""); } function trim(string) { return trimEnd(trimStart(string)) }
ãã ããã»ãšãã©ã®å Žåãæ©èœã¯å¿ èŠãªæªã®ããã«èŠããŸããããããåãé€ãããšã¯ã§ããŸããã ããšãã°ãé 延ã³ãŒã«ã®ã³ãŒã«ããã¯é¢æ°ãæž¡ããã³ã«ãã³ãŒã«ããã¯ã«ã¯äžæã®ã³ã³ããã¹ããå¿ èŠã§ãã éåžžãã³ã³ããã¹ãã¯ãã¯ããŒãžã£ãŒã䜿çšããããšã«ãããã·ã³ãã«ã§çŽæçã§ããéå¹ççãªæ¹æ³ã§å®è£ ãããŸãã ç°¡åãªäŸãšããŠãæšæºã®éåæã³ãŒã«ããã¯ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããŠãJSONããããŒãã«ãã¡ã€ã«ãèªã¿åããŸãã
var fs = require('fs'); function readFileAsJson(fileName, callback) { fs.readFile(fileName, 'utf8', function(error, result) { // readFileAsJson. // , Context // . if (error) { return callback(error); } // try-catch // - JSON try { var json = JSON.parse(result); callback(null, json); } catch (e) { callback(e); } }) }
ãã®äŸã§ã¯ã fs.readFile
æž¡ãããã³ãŒã«ããã¯ã¯ãäžæã®callback
å€æ°ã®åšãã«ã¯ããŒãžã£ãŒãäœæããããã readFileAsJson
ããfs.readFile
ããšãã§ããŸããã ååä»ãé¢æ°ã«å¿åã®ã³ãŒã«ããã¯ãè©Šã¿ãŠãäœãèµ·ãããªãããšã«æ³šæããŠãã ããã
Bluebirdå ã§åžžã«äœ¿çšãããæé©åã¯ãæ瀺çãªåçŽãªãªããžã§ã¯ãã䜿çšããŠã³ã³ããã¹ãããŒã¿ãä¿æããããšã§ãã å€ãã®ã¬ãã«ã§ã³ãŒã«ããã¯ã転éããã«ã¯ããã®ãããªãªããžã§ã¯ãã®1ã€ã ãã«ã¡ã¢ãªãå²ãåœãŠãå¿ èŠããããŸãã åã¬ãã«ã§æ°ããã¯ããŒãžã£ãŒãäœæãã代ããã«ãã³ãŒã«ããã¯ã次ã®ã¬ãã«ã«æž¡ããããšãã«ãè¿œå ã®åŒæ°ã䜿çšããŠæ瀺çãªåçŽãªãªããžã§ã¯ããæž¡ããŸãã ããšãã°ãå ã®é¢æ°ã«5ã€ã®ã¬ãã«ãããå Žåãã¯ããŒãžã£ãŒã䜿çšãããšã5ã€ã®é¢æ°ãšContextãªããžã§ã¯ããããããšå ±ã«äœæãããããšãæå³ããŸãã ãã®æé©åã®å Žåããããã®ç®çã®ããã«1ã€ã®ãªããžã§ã¯ãã®ã¿ãäœæãããŸãã
fs.readFile
ãå€æŽããŠã³ã³ããã¹ããªããžã§ã¯ããæž¡ãããšãã§ããå Žåãæé©åã¯æ¬¡ã®ããã«é©çšã§ããŸãã
var fs = require('fs-modified'); function internalReadFileCallback(error, result) { // readFile callback , // `this`, // if (error) { return this(error); } // try-catch // - JSON try { var json = JSON.parse(result); this(null, json); } catch (e) { this(e); } } function readFileAsJson(fileName, callback) { // fs.readFile . // , callback, // fs.readFile(fileName, 'utf8', internalReadFileCallback, callback); }
ãã¡ãããAPIã®äž¡æ¹ã®éšåãå¶åŸ¡ããå¿
èŠããããŸã-ã³ã³ããã¹ããã©ã¡ãŒã¿ãŒã®ãµããŒããªãã§ã¯ããã®ãããªæé©åã¯é©çšã§ããŸããã ãã ããããã䜿çšããå ŽåïŒããšãã°ãå€ãã®å
éšã¬ãã«ãå¶åŸ¡ããå ŽåïŒãããã©ãŒãã³ã¹ã®åäžã¯é¡èã§ãã ããŸãç¥ãããŠããªãäºå®ïŒ Array.prototype.forEach
ãªã©ã®äžéšã®çµã¿èŸŒã¿JavaScript Array APIã¯ã2çªç®ã®ãã©ã¡ãŒã¿ãŒãšããŠã³ã³ããã¹ããªããžã§ã¯ããArray.prototype.forEach
ãŸãã
2.ãªããžã§ã¯ãã®ãµã€ãºãæå°åããŸã
é »ç¹ã«äœæããããªããžã§ã¯ããšãPromiseãªã©ã®å€§éã«äœæããããªããžã§ã¯ãã®ãµã€ãºãæå°éã«æããããšãéèŠã§ãã ã»ãšãã©ã®JavaScriptå®è£ ã§ãªããžã§ã¯ããäœæãããããŒãã¯ãå æé åãšç©ºãé åã«åããããŸãã å°ãããªããžã§ã¯ãã¯å€§ãããªããžã§ã¯ããããé·ã空ãã¹ããŒã¹ãåãããã®çµæãã¬ããŒãžã³ã¬ã¯ã¿ãŒã®äœæ¥ãå°ãªããªããŸãã ãŸããéåžžãå°ããªãªããžã§ã¯ãã«ã¯å«ãŸãããã£ãŒã«ããå°ãªãã®ã§ãã¬ããŒãžã³ã¬ã¯ã¿ãŒã¯ãããã®åšããç°¡åã«ç§»åããŠãã©ã€ããªããžã§ã¯ããšããããªããžã§ã¯ããããŒã¯ããŸãã
ããŒã«ããã³/ãŸãã¯å¶éãããæ°ã®ãã£ãŒã«ãã¯ã ãããåäœã®æäœã«ãã£ãŠããã«å§çž®ãããŸã ã JavaScriptã®ãããæŒç®ã¯ã32ãããã®æ°å€ã§æ©èœããŸãã 1ã€ã®ãã£ãŒã«ãã«ã¯ã32åã®ããŒã«ãã£ãŒã«ãã8åã®4ãããæ°ã16åã®ããŒã«å€ãš2åã®8ãããæ°ãªã©ãé 眮ã§ããŸããã³ãŒããèªã¿ãããããã«ã¯ãåè«çãã£ãŒã«ãã«å¿ èŠãªãããæŒç®ãå®è¡ããã²ãã¿ãŒãšã»ãã¿ãŒãå¿ èŠã§ãç©ççãªæå³ã 1ã€ã®ããŒã«åãã£ãŒã«ããæ°å€ã«å§çž®ããæ¹æ³ã®äŸã次ã«ç€ºããŸãïŒä»ã®è«çãã£ãŒã«ãçšã«ããã«å±éã§ããŸãïŒã
// 1 << 1 , 1 << 2 .. const READONLY = 1 << 0; class File { constructor() { this._bitField = 0; } isReadOnly() { // . return (this._bitField & READONLY) !== 0; } setReadOnly() { this._bitField = this._bitField | READONLY; } unsetReadOnly() { this._bitField = this._bitField & (~READONLY); } }
ã¢ã¯ã»ã¹ã¡ãœããã¯éåžžã«çãã®ã§ãã»ãšãã©ã®å Žåãè¿œå ã®é¢æ°åŒã³åºããªãã§ã©ã³ã¿ã€ã ã«çµã¿èŸŒãŸããŸãã
翻蚳è ã®ã¡ã¢ïŒ JavaScriptã³ã³ãã€ã©ãŒã®æäœã«é¢ããåºæ¬æ å ±ãã€ã³ã©ã€ã³ãã£ãã·ã³ã°ãšåã蟌ã¿é¢æ°ã®æŠå¿µã«ã€ããŠã¯ãèšäºã JavaScriptã³ã³ãã€ã«ã®éå»ãšæªæ¥ããåç §ããŠãã ããã ãªããã£ãã€ã¶ãŒã®åäœã«ã€ããŠ-Petka Antonovã«ããæé©åãã©ãŒ ïŒãªãªãžãã«ã®æŽæ°ããããŸãïŒããã³Optimization Killerã®ç¿»èš³ïŒ2014幎ã«å ¬éïŒã
åæã«äœ¿çšãããªã2ã€ä»¥äžã®ãã£ãŒã«ãã¯ããã£ãŒã«ãã«é 眮ãããå€ã®ã¿ã€ãã远跡ãããã©ã°ã䜿çšããŠ1ã€ã®ãã£ãŒã«ãã«å§çž®ã§ããŸãã ãã ããäžèšã®ããã«ããã©ã°ãå§çž®ãããæ°å€ãšããŠå®è£ ãããŠããå Žåã«ã®ã¿ããã®ã¡ãœããã¯ã¹ããŒã¹ãç¯çŽããŸãã
Bluebirdã§ã¯ããã®ããªãã¯ã䜿çšããŠãçŽæã®äŸ¡å€ãŸãã¯æåŠã®çç±ãä¿æããŸãã ããã«ã¯å¥ã®ãã£ãŒã«ãã¯ãããŸãããçŽæãæºããããå Žåãå®è¡ã®çµæã¯æåŠã³ãŒã«ããã¯ã®ãã£ãŒã«ãã«æ ŒçŽãããçŽæãæåŠãããå ŽåãæåŠã®çç±ã¯æåå¿çã³ãŒã«ããã¯ãã£ãŒã«ãã«ä¿åãããŸãã ç¹°ãè¿ããŸãããå€ãžã®ã¢ã¯ã»ã¹ã¯ãå®è£ ã®è©³çŽ°ãé ãã¢ã¯ã»ã¹é¢æ°ãä»ããŠè¡ãå¿ èŠããããŸãã
ãªããžã§ã¯ãã«ãšã³ãã£ãã£ã®ãªã¹ããä¿åããå¿ èŠãããå Žåã¯ããªããžã§ã¯ãã®ã€ã³ããã¯ã¹ä»ãããããã£ã«å€ãçŽæ¥ä¿åããããšã«ãããåå¥ã®é åã®äœæãåé¿ã§ããŸãã æžã代ããã«ïŒ
class EventEmitter { constructor() { this.listeners = []; } addListener(fn) { this.listeners.push(fn); } }
é åãé¿ããããšãã§ããŸãïŒ
class EventEmitter { constructor() { this.length = 0; } addListener(fn) { var index = this.length; this.length++; this[index] = fn; } }
.length
ãã£ãŒã«ããå°ããªæ°ã«å¶éã§ããå ŽåïŒããšãã°ã10ããããã€ãŸãã event emitter
ã¯æ倧1024人ã®ãªã¹ããŒãæã€ããšãã§ããŸãïŒãä»ã®å¶éãããæ°ãšããŒã«å€ãå«ãããããã£ãŒã«ãã®äžéšã«ããããšãã§ããŸãã
3. no-opé¢æ°ã䜿çšããŸãã é«äŸ¡ãªãªãã·ã§ã³æ©èœãå®è£ ããããã«ããããé 延çã«æžãæããŸã
Bluebirdã«ã¯ã䜿çšæã«ã©ã€ãã©ãªå šäœã®ããã©ãŒãã³ã¹ãåäžã«äœäžãããããã€ãã®ãªãã·ã§ã³æ©èœãå«ãŸããŠããŸãã ãããã¯ãvoringsãã¹ã¿ãã¯ãã¬ãŒã¹ããã£ã³ã»ã«ããæ©èœãPromise.prototype.bindãpromiseã®ã¹ããŒã¿ã¹ã®ç£èŠãªã©ã§ãã ãããã®é¢æ°ã«ã¯ãã©ã€ãã©ãªå šäœã§ã€ã³ã¿ãŒã»ãã¿ãŒåŒã³åºããå¿ èŠã§ãã ããšãã°ãPromiseç£èŠæ©èœã§ã¯ãPromiseãäœæãããã³ã«ã€ã³ã¿ãŒã»ãã¿ãŒãåŒã³åºãå¿ èŠããããŸãã
å®éã®ç¶æ ã«é¢ä¿ãªããæ¯åç£èŠæ©èœãèµ·åããããããç£èŠæ©èœããªã³ã«ãªã£ãŠãããã©ãããåŒã³åºãåã«ç¢ºèªããæ¹ãã¯ããã«ç°¡åã§ãã ãã ããã€ã³ã©ã€ã³ãã£ãã·ã¥ïŒ 翻蚳è ã®ã¡ã¢ïŒãããã¯ã«é¢ããå¥ã®ã¡ã¢ ïŒãšæ©èœã®çµ±åã®ãããã§ããã®æäœã¯ç£èŠãç¡å¹ã«ããŠãããŠãŒã¶ãŒã«å¯ŸããŠå®å šã«ç°¡çŽ åã§ããŸãã ãããè¡ãã«ã¯ã空ã®é¢æ°ãå ã®ã€ã³ã¿ãŒã»ãã¿ãŒã¡ãœããã«å²ãåœãŠãŸãã
class Promise { // ... constructor(executor) { // ... this._promiseCreatedHook(); } // no-op . _promiseCreatedHook() {} }
çŸåšããŠãŒã¶ãŒãç£èŠæ©èœãæå¹ã«ããŠããªãå Žåããªããã£ãã€ã¶ãŒã¯ã€ã³ã¿ãŒã»ãã¿ãŒãäœãããŠããªãããšã確èªãããããç°¡çŽ åããŸãã ã³ã³ã¹ãã©ã¯ã¿ãŒã«ã€ã³ã¿ãŒã»ãã¿ãŒã¡ãœãããååšããªãããšãããããŸãã
ç£èŠæ©èœãæ©èœããããã«ã¯ãç£èŠæ©èœãå«ãããšãé¢é£ãããã¹ãŠã®no-opæ©èœãå®éã®å®è£ ã«äžæžããããŸãã
function enableMonitoringFeature() { Promise.prototype._promiseCreatedHook = function() { // }; // ... }
ãã®ãããªã¡ãœããã®æžãæãã«ãããPromiseã¯ã©ã¹ã®ãªããžã§ã¯ãçšã«äœæãããã€ã³ã©ã€ã³ãã£ãã·ã¥ãç¡å¹ã«ãªããŸãã ããã¯ãçŽæãäœæãããåã«ãã¢ããªã±ãŒã·ã§ã³ã®èµ·åæã«è¡ãå¿ èŠããããŸãã ãããã£ãŠããã®åŸã«äœæãããã€ã³ã©ã€ã³ãã£ãã·ã¥ã¯ãno-opé¢æ°ãååšããããšãèªèããŸããã
ãªãªãžãã«ïŒPetka Antonovã«ããBluebirdãé«éã«ãã3ã€ã®JavaScriptããã©ãŒãã³ã¹ã®åºç€ ã
ç¿»èš³ïŒ aalexeev ã æ¹èšè ïŒ jabher ã