LTããã¼ã éçºã«ããã¦Nodeæªçµé¨è ã®å¦ç¿ã³ã¹ããä¸ããããã®å·¥å¤«ãã®è£è¶³
å æ¥ãæ±äº¬Nodeå¦å18æéç®ãNode.js 4.0ã®è©±ãã®åã§ãLTãããã¦ããã ãã¾ããã
Node学園 18時限目 Node.js v4.0の話 - connpass
è³æã¯ãã¡ãã§ãã
ããã10åã¨ããã©ã120人*10å=20人æéã¨ãããã¬ãã·ã£ã¼ãåå¼·ä¼çã§çºè¡¨ããã®ã¯ãããåãã¦ã§ããã®1é±éã¯ã²ããããã®LTã®ãã¨ã ããèãã¦çæ´»ãã¦ãããããªã
ãã¼ãã¯åãã«æãåã£ã¦è¨å®ãããã®ã®ãã¾ãã¯ãã®1å¹´ã®éçºãæ¯ãè¿ãä½ããã¤ã³ãã ã£ãã®ããèããã¨ããããã»ã»ã»ã
ãããããããããä½ã£ã¦è©±ãç·´ç¿ããã¦ã¿ãã¨ãã©ãã話ãç¹ã£ã¦ããªãã£ãããæè¡çãªè©±ãå°ãªããã¦ãããããNodeã®ä¼åã«æ¥ã¦ããã客ããã«ç³ã訳ãªãããªããã¨ãããããªå
容ã ã£ããã¨ãå
容ãã¾ã¨ãä¸ããã®ã«è¦å¿ãã¾ããã
ãããªè¦å´ããã£ãæºåã®ç²æããããè¯ãåå¿ãé ããã²ã¨ã¾ãããã¨ãã¦ããæ¬¡ç¬¬ã§ãã
ããã¯ãã³ãã«ä¼ç¤¾ã«æã¡å¸°ããã話 #tng18
— fnwiya (@fnwiya) October 8, 2015
ãã話ã ã£ã #tng18
— Kohei Asai (@axross_) October 8, 2015
ä¼å ´ã«ããããçæ§ããæ¸ è´ãããã¨ããããã¾ããã
ãã¦ãè³æã«ã¯ä¸å¿è¼ããããã©ãçºè¡¨æã«ãã¹ã©ã¤ãä¸ã§ãåå説æã§ãã¦ããªãç¹ã«ã¤ãã¦ããã®ã¨ã³ããªã§å°ãè£è¶³ãããã¦ããã ãããã¨æãã¾ãã
lodashã®ãã¼ã¸ã§ã³ã«ã¤ãã¦
lodashã¯v2.4.1ã§ãã°ããã®éãªãªã¼ã¹ãæ¢ã¾ã£ã¦ãã¾ããããç´1å¹´åãããã«v3ããªãªã¼ã¹ãããã¦ããããv4ããªãªã¼ã¹ããããã§ãã
ç¹å¾´ã¨ãã¦ãv2 => v3, v3 => v4 ã§ã®breakingãªå¤æ´ãå²ã¨å¤ãã§ããéç¨ã«å
¥ã£ã¦ãã¾ãã¨ã¡ã¸ã£ã¼ãã¼ã¸ã§ã³ãæããã®ã¯çµæ§å¤§å¤ã«ãªã£ã¦ãã¾ãã¤ã¡ã¼ã¸ã§ãã
è³æã«ã¡ãã£ã¨æ¸ãã¾ãããããã¾ããéçºå§ãããªããv4ãåºãã¾ã§(åºã¦ãããã°ããã¾ã§)ãä¾åå
ãedge(githubä¸ã®masterã®ææ°)ã«ãã¦ããã®ãè¯ãããããªãããªã¨æã£ã¦ãã¾ãã
v4ã®ç¹å¾´ã¨ãã¦ã¯ãä»ã¾ã§1ã¤ã®é¢æ°ã«ããã¤ãã®å¼æ°ã®æ¸¡ãæ¹ãã§ãã¦ããã¨ãããã颿°èªä½ãåããããã«å¤æ´ããªããã¾ãã
ä¾ãã°_.uniq
ã¨ãã颿°ã¯ãã³ã¬ã¯ã·ã§ã³ã渡ãã¨éè¤ããå¤ã1ã¤ã ãã«ããé
åãè¿ãã¾ããããã®_.uniq
ã®å¼æ°ã«é¢æ°ãä¸ããã¨ããã®é¢æ°ãéããçµæã«å¯¾ãã¦ãuniqãããããã¨ãã仿§ã§ããã
ãããã_.uniq
ã¨_.uniqBy
ã¨ãã2ã¤ã®é¢æ°ã«ãããã颿°ã渡ããããã°å¾è
ã使ããã¨ã«ãªãã¾ãã
ãã®ããã«ãã·ã³ãã«ãªæ¹åã«åãã¦ããã®ãlodashã®è¯ãæã®ä¸ã¤ã§ããã¾ãã
ãã®ä»ãaliasã大éã«åé¤ããããã§ããunderscoreã«ãã£ãã¡ã½ããã«å¯¾ãã¦ãlodash v3ã§å¥ã®ååãã¤ãã¦ããã¦ãå ã®ååã«ã¯aliasãè²¼ã£ã¦ããããv4ã§ãã®aliasãåé¤ãããªãã¦ã±ã¼ã¹ãããããã¾ã§ãããã»ã»ï¼ï¼(lodashã®ä½è jdaltonã¨underscoreã®ä½è jashkenasã¯ä»²æªãã§ã)
ãªãããã°ã¯ãããªãã«ããã¾ããä¸è¦æ¨¡ãããã§ã¬ãããªä½¿ã£ã¦ããã¨åºããããã¨ãããã¨æãã¾ããç¹ã«v3ã®åæã¯ãé å»¶è©ä¾¡ã¾ããã®ãã°ãçµæ§ããã¾ãããissueã軽ã追ã£ã¦ãããã»ããè¯ãã§ãã
async#waterfallã¨neo-async#angelFallã®è©±
ãããã¸ãã¯ãæ¸ãæ¹ãªã¿ã¯ã¨ãã¦ã¯çµæ§ãã ããã®ããã¨ããã§ãããã³ã¨æ¸ãã¦ãããã話ãªã®ã§ããã¾ãä»åº¦ã®æ©ä¼ã«ãã¾ã><
lodashã®ã¯ã¨ãªã®æ¸ãæ¹
ãªãã¸ã§ã¯ãã並ã¶é
åarrä¸ãããããããã£xã®å¤ã2ã§ãããã®ãè¦ã¤ããã¨ãã
_.find(arr, function(obj) { return obj.x === 2; })
ã®ãunderscoreããããæ¸ãæ¹ã§ãããããã
_.find(arr, { x: 2 })
ã¨ããæ¸ãæ¹ãã§ãã¾ããããã«å¥ã®æ¸ãæ¹ã¨ãã¦ã
_.find(arr, 'x', 2)
ã¨ããæ¸ãæ¹ãããã¾ããé¢ç½ãã§ããã
å人çã«ã¯2ã¤ãã®_.find(arr, { x: 2 })
ãè¯ãããªã¨æã£ã¦ãã¾ãã
3ã¤ãã«ããªãçç±ã¯ãä¾ãã°ãxã2, yã3ã®ãã®ãæ¢ããã¨ãã«_.find(arr, {x: 2, y: 3})
ã¨ããæ¸ãæ¹ãã§ãã¾ããã3çªç®ã®æ¸ãæ¹ã ã¨å¿ç¨ãå¹ããªããªã£ã¦ãã¾ãããã§ãã
ä½è«ã§ãããlodashããããã§ã_.includes
ã使ãã¹ãå ´é¢ã§ééã£ã¦_.some
ã使ã£ã¦ãã¾ããã¨ããã®ãããã¾ãã
åè
ã¯åãªãå³å¯ãªæ¯è¼ã§å«ã¾ãã¦ããã°trueãè¿ããå¾è
ã¯ä¸ã®_.find
ã¨åãæãã§ãè¦ã¤ãã£ããtrueãè¿ãã
ãããªãã¸ã§ã¯ããã®ãã®ãããé
åã«å
¥ã£ã¦ãããã調ã¹ãããã¤ã¾ã_.includes(arr, obj)
ã¨ãããã¨ããã§ã
ééãã¦_.some(arr, obj)
ãªãã¦æ¸ãã¨ããªãã¸ã§ã¯ãå士ã®ããããã£ã1ã¤ãã¤(ãããdeepã«)æ¯è¼ãã¯ããã¦ãã¾ãã
大æµã®å ´åã§çµæãä¸è´ãã¦ãã¾ãã®ã§ãã¹ãæ¸ãã¦ããã°ã«æ°ã¥ãã«ããã
çµæãæãã¬ã¨ããã§ããã©ã¼ãã³ã¹ã®åé¡ãå¼ãèµ·ããã¦ãã¾ãããããã¾ãããã
ä½åº¦ãè¦ãããäºä¾ã§ãããlodashãªã¿ã¯ãªãã³ã¼ãã¬ãã¥ã¼ã§ééãã«æ°ä»ããã¨ãåºæ¥ã¾ãw
undefinedãã§ãã¯ã®è©±
LTã§æãåå¿ãè¯ãã£ããundefinedãã§ãã¯ã®è©±ã§ãã
è³æä¸ã§ã¯ä»¥ä¸ã®4ç¹ã®æ¹æ³ãæãã¦ãã¾ãã
x === undefined
x === void 0
typeof x === 'undefined'
_.isUndefined(x)
undefined ã夿°ã«å
¥ãããããã©ãããã¨ãèãããããªããã x === undefined æ´¾é¥ #tng18
— Yosuke FURUKAWA (@yosuke_furukawa) October 8, 2015
æè¿ãæ¯è¼ã«void 0 使ã£ã¦ãªãã§ããããã£ã¦è¨ãããä»¶ #tng18
— ãã (@rei_m) October 8, 2015
ã¡ãªã¿ã«LTä¸ã§ä¼å ´ã®æ¹ã«ã©ãã使ããææã§ã¢ã³ã±ã¼ããã¨ããã¦ããã ãã¾ãããã大使æã®æ¯ç㯠6:4:10:1 ãããã ã£ãå°è±¡ã§ãã
ãã¦ãèªåã¯typeof x === 'undefined'
ãè¯ããªãã¨èãã¦ããæ¨ã話ãã¾ããããã®ç¹ãæ´çãããã¨æãã¾ãã
typeof x === 'undefined'ã ã¨ReferenceErrorãæ¡ãã¤ã¶ããã¨ãããã®ã⦠#tng18
— Toshiya SAITOH (@stoshiya) October 8, 2015
ã¾ããtypeof x === 'undefined'
ã¯1ã¤ã®JavaScriptã®ã¤ãã£ãªã ã§ãããã®æ¸ãæ¹ãããã¨ãããä»®ã«xããããã夿°ã¨ãã¦å®ç¾©ããã¦ããªãå ´åã§ããReferenceErrorãåããã¨ããªããä¸ã®å¼ã®çµæã¯trueã«ãªãã¾ãããã©ã¦ã¶ä¸ã§ãç¹ã«ã°ãã¼ãã«ã«å¤æ°xã宣è¨ããã¦ãããã©ããããã§ãã¯ããå ´åãªã©ã«æç¨ã§ãããã¨ããããã使ããã¾ããReferenceErrorãåããªãããå®å
¨ãã¨ããè¨ããæ¹ããããã¨ãããã¾ãã
ããããªãããNode.jsã§ã¯ã°ãã¼ãã«å¤æ°ããã§ãã¯ãããã¨ã¯ã¾ãããã¾ããããã®ã¨ãã«ããReferenceErrorãåããªãããã¨ããå®å ¨ããªã®ãï¼ã¨ããçåãçãã¾ãã
ä¾ãã°å¤æ°åãtypoãã¦ãã¾ã£ãããã®ã¨ãã¯ReferenceErrorãåãã®ããããæ£ããåä½ã§ããããªããªãã¨ãããã¨ã¯ãåãããã¹ãã¨ã©ã¼ãæ¡ãã¤ã¶ãã¦ãããã¨ã«ä»ãªããªãããã§ãããã«ãããã¹ã«æ°ä»ãæ©ä¼ãé¸ããããããã¾ããã"è¯ããªãæ¸ãæ¹"ã§ããã¨èããã®ã¯ãã®ç¹ã§ãã
ãã¦ãæ¸ãæ¹ãã©ãã«ãããã§ããã¨ãå°ãæµæããæ¹ãããããããã¾ããããä»æã¯ x === undefined
ã§åé¡ãªãã¨è¨ã£ã¦ããã§ãããã
ä¸å¿var undefined = 1;
ããããã¨ãããã(ã ãã©ãããªãã¨ãã人å±
ãªãããæ°ã«ããªãã)ã¨è©±ãã¾ãããã
Node 4.xã§'use strong;'
ããã¨ãããã§ããªããªãããã§ãã
ãã StrongScript ã ã£ãã var undefined = 1; é²ãããï¼ï¼ï¼ #tng18
— Yosuke FURUKAWA (@yosuke_furukawa) October 8, 2015
ã¨ããããã§ãä¸çªã·ã³ãã«ãªx === undefined
ã§è¯ãããããªãã§ããããã
æ¸ãæ¹ãªã¿ã¯ãè¤æ°äººãããï¼
æ¸ãæ¹ãªã¿ã¯ãè¤æ°äººãã¦ã¾ã¨ã¾ããªã話ã¨ãç¡ãã®ã㪠#tng18
— ã®ã³ãã/S.Ryousuke (@n0bisuke) October 8, 2015
ããã«å¯¾ãããèªåã®è§£æ±ºçã¯ä»¥ä¸ã§ãã
- æçµæ±ºå®ããã人(ãªã¼ãã¼)ã¯1人ã«ããã
- ãæ¸ãæ¹ãçµ±ä¸ããã¦ããããã¨ãæéè¦ã§ããã å ¨ã¦ã®æ¸ãæ¹ãªã¿ã¯ã¯ãããèã«éãã¦ããã
1ã®æ¹ã¯ãæ¸ãæ¹ã«éã£ã話ã§ã¯ãªãã§ããããã¨ã«ããæ±ºå®ãã人ã2人ããã¨é¢åãã®ä¸ããã¾ãããæåäºä¾ã¨ããéçºããåæã«ããã«ãªã¼ãã¼ã®ãããªç¶æ ã«ãªã£ãã¨ãã¯è¯ããªãã£ãã
2ã®æ¹ã¯ãç§ã®LTã§æ¥µæã®3ã¤ãã¨ãã¦è©±ãã¦ãããã®ã§ããããã¯ä»ãããããã¦ãªã«ãããéè¦ã ã¨ç§ã¯èãã¦ãã¾ãã
è¯ãå®ä¾ãããã¾ãã
åããã£ããã«ä»äºããä¸ã§ã®ä»£è¡¨çãªæ¸ãæ¹ãªã¿ã¯ã«ãneo-asyncã¨ãã人ç©(?)ããã¾ããã¡ããã©åã®åã«LTãè¡ã£ã人ã§ãã
neo-async
LT ãNeo-Asyncã
åã¨å½¼ã¯ããã£ã¡ã ãæ¸ãæ¹ã«ã¤ãã¦è°è«ããã¾ãããã®çµæã50%ã¯æçµçã«æè¦ãåè´ãã¾ãããæè¦ãåããã«çµãããã¨ã50%ããã¾ãã
ä¾ãã°ããã®è¨äºã®ä¸ã®ã»ãã§lodashã®ã¯ã¨ãªã®è©±ããã¦ãã¾ãããå½¼ã¯3ã¤ãã®_.find(arr, 'x', 2)
ã¨ããæ¸ãæ¹ãè¯ãã¨è¨ãã¾ããå½¼ã¯ä½ã話ãã¨ãã¯å¸¸ã«ãã³ããã¼ã¯ãåã£ã¦ããã確ããã®ä»¶ã§ã¯ããã®ã»ãã2åãããéããããããéãæ¸ãæ¹ãããã®ã§ãããæ¾æ£ããå¿
è¦ããªããããã¨ãã主張ã§ããã
ç§ã¯ã¨ããã¨ãã©ãã2ã¤ãã®_.find(arr, { x: 2 })
ã®æ¸ãæ¹ã¯è¦ããªããã°ãããªãã®ã§ã(_.find(arr, { x: 2, y: 1 })
ã®ãã¿ã¼ã³ããããã)ãå¦ç¿ã³ã¹ããæ¸ããããã®ã§2ã¤ãã§çµ±ä¸ãããã
ã©ã¡ããæ£ããã¨ãããã¨ã¯ãªãã¨æãã¾ãã
ãã以å¤ã«ãæ¬å½ä¸ããªããã¨ã§ããã£ã¡ã
ãè¨ãåã£ã¦ãã¾ãã_.each
ã_.forEach
ããªã©ãèªåã®ä¼è©±ã§ãªããã°å³åº§ã«ãããã¨ã©ãã§ããããã®AAãè²¼ã£ã¦ãããããããã§ãã
以ååããã¼ã ã§ä»äºããã¨ãã¯ãã¾ãã¾ãç§ããã¨ãã¨ãããã¼ã ã«å½¼ãå©ã£äººçã«å ¥ã£ã¦ããã¦ãããã¨ããããçµæçã«ã¯æçµçã«ã¯ç§ã®æè¦ãã»ã¼100%éãå½¢ã«ãªã£ã¦ãã¾ãã¾ããããã¡ããå½¼ã®ä¸ã§ã¯ãèªåãè¯ãã¨æãæ¸ãæ¹ãåºæ¥ãªã䏿ºã¯ãã£ãã®ã§ã¯ãªããã¨æãã¾ããã³ã¼ãã¬ãã¥ã¼ã§ã¯ã"殺ãã¦ã§ã ãã°ãã¨ã"ã§ã¯ãªã"ããã£ã¦ãã ãã®ãï¼"ã«ããããããã§ãã(LTè³æã®çµããã®æ¹ãåç §ãããã)ã
ãã¡ããæè¦ã¯è¨ã£ã¦ããã¾ããããã以ä¸ã¯ãã®äººã®èãæ¹ãããã¯æ°åã ãããªãã¨ããã¨ããã§ãããã«åããã¦ä¿®æ£ãã¦ããã¦ãã¾ãããããã¯ã¤ã¾ãã¨ãããåãããã®ãæã大äºã ã¨èãã¦ããããã§ããéã«å½¼ã®ãã¼ã ã«ç§ãå ¥ãå½¢ã ã£ãããç§ã®ã»ããåããããã¨ãæèããã¨æãã¾ãã(å½¼ã¯ã«ããã«è±èªåå¼·ã®æ ã«åºã¦ãã¾ãã®ã§ãå°ãªãã¨ãå½åä¸ç·ã«ä»äºããæ©ä¼ããªãã®ã¯æ®å¿µã§ããã)
ãã¨ã¯ããã¾ããã¸ã«ã«ã§ãªã主張ãããããéãã¨è¯ããªãã¦(ãããããã¨ãå®éãã£ã)ãå人çã«ã¯ããã¨ç´°ãããã¨ã§ãã¡ããã¨è©±ãã®ãè¯ãã®ããªã¨æã£ã¦ãã¾ããã¡ãã£ã¨å¤§å¤ã§ãããæ¸ãæ¹ããã©ãã©ã«ãªãã¨ãããªã¹ã¯ã¯ããã»ã©å¤§ããã¨ãããã¨ã§ãã
asyncæ¸ãæ¹æ¯è¼ã®ã½ã¼ã¹ã³ã¼ã
asyncã®æ¸ãæ¹ã®ä¾ã3ã¤æãã¦æ¯è¼ããã¹ã©ã¤ããå ¥ãã¾ããããæåã®æ å ±ã«ããããã«ãã¡ãã«è¼ãã¦ãããã¨æãã¾ãã
æºå
var async = require('neo-async'); var getFoo = function(callback) { return callback(null, { x: 1 }); }; var getBar = function(x, callback) { return callback(null, x + 1); }; var doBaz = function(callback) { return callback(null, 'piyo'); }; var doQux = function(foo, bar, callback) { return callback(null, 'baz'); };
plain (callback hell)
var ex_plain = function(callback) { // fooãåå¾ãã. getFoo(function(err, foo) { if (err) { return callback(err); } // fooããã«ããã«ããã. foo.hoge = 1; foo.fuga = 2; // barãåå¾ãã. getBar(foo.x, function(err, bar) { if (err) { return callback(err); } doBaz(function(err, result) { if (err) { return callback(err); } foo.piyo = result; doQux(foo, bar, function(err, baz) { if (err) { return callback(err); } // ... callback(null, { foo: foo, bar: bar, baz: baz}); }); }); }); }); };
async.series (å¼ç¤¾ã§å¤ã)
var ex_series = function(callback) { var foo, bar, baz; async.series([ function(next) { // fooãåå¾ãã. getFoo(function(err, _foo) { if (err) { return next(err); } foo = _foo; // fooããã«ããã«ããã. foo.hoge = 1; foo.fuga = 2; next(); }); }, function(next) { // barãåå¾ãã. getBar(foo.x, function(err, _bar) { if (err) { return next(err); } bar = _bar; next(); }); }, function(next) { doBaz(function(err, result) { if (err) { return next(err); } foo.piyo = result; next(); }); }, function(next) { doQux(foo, bar, function(err, _baz) { if (err) { return callback(err); } // ... baz = _baz; next(); }); }, ], function(err) { if (err) { return callback(err); } callback(null, { foo: foo, bar: bar, baz: baz }); }); };
async.waterfall 1 (æ¨å¥¨)
var ex_waterfall = function(callback) { var foo, bar; async.waterfall([ function(next) { // fooãåå¾ãã. getFoo(next); }, function(_foo, next) { foo = _foo; // fooããã«ããã«ããã. foo.hoge = 1; foo.fuga = 2; // barãåå¾ãã. getBar(foo.x, next); }, function(_bar, next) { bar = _bar; doBaz(next); }, function(result, next) { foo.piyo = result; doQux(foo, bar, next); }, function(baz, next) { // ... next(null, { foo: foo, bar: bar, baz: baz }); } ], callback); };
async.waterfall 2
var ex_waterfall2 = function(callback) { async.waterfall([ function(next) { // fooãåå¾ãã. getFoo(next); }, function(foo, next) { // fooããã«ããã«ããã. foo.hoge = 1; foo.fuga = 2; // barãåå¾ãã. getBar(foo.x, function(err, bar) { next(err, foo, bar); }); }, function(foo, bar, next) { doBaz(function(err, piyo) { next(err, foo, bar, piyo); }); }, function(foo, bar, piyo, next) { foo.piyo = piyo; doQux(foo, bar, function(err, baz) { next(err, foo, bar, baz); }); }, function(foo, bar, baz, next) { // ... next(null, { foo: foo, bar: bar, baz: baz }); } ], callback); };