Top Banner
ServerSide ES6  (╹◡╹)ノ timakin / @timadayon
44

Serverside ES6@Livesense technight

Apr 16, 2017

Download

Engineering

Seiji Takahashi
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Serverside ES6@Livesense technight

ServerSide ES6  (๑╹◡╹๑)ノ

timakin / @timadayon

Page 2: Serverside ES6@Livesense technight

こんにちはこんにちは!

Page 3: Serverside ES6@Livesense technight

Profile: - DeNA入社1年目 - エンジニア - github: timakin - blog: timakin.log

およそ8~9ヶ月ほど リブセンス(様) にはお世話になりました

Page 4: Serverside ES6@Livesense technight

Twitter: @timadayon

idも画像も違う。 気分で下手に 変えていいもんじゃない。

Page 5: Serverside ES6@Livesense technight

[某所での初タスク]

JavaScriptでのちょっとしたDOM操作

Page 6: Serverside ES6@Livesense technight

僕が取った手段

Page 7: Serverside ES6@Livesense technight

getElementById(..) onClick=“hoge()”

Page 8: Serverside ES6@Livesense technight

jQueryってものがあってな。

Page 9: Serverside ES6@Livesense technight

リブセンス様、その節はほんとうに 温かい目で見守ってくださって ありがとうございました。

ほんっとに死ぬほど感謝してます。

Page 10: Serverside ES6@Livesense technight

時は流れましたが…

Page 11: Serverside ES6@Livesense technight

今日は

Page 12: Serverside ES6@Livesense technight
Page 13: Serverside ES6@Livesense technight

一部ES6の紹介と、 フロントエンドではなく、 サーバーサイドの言語として

ES6を実際に使ってみたときの話。

Page 14: Serverside ES6@Livesense technight

• Block scoping

• Classes (strict mode only)

• Collections

• Typed arrays

• Generators

• Binary and Octal literals

• Object literal extensions

• Promises

• New String methods

• Symbols

• Template strings

• Arrow Functions

ES6 features ship with Node.js by default(v4.2.1)

Page 15: Serverside ES6@Livesense technight

• Block scoping

• Classes (strict mode only)

• Collections

• Typed arrays

• Generators

• Binary and Octal literals

• Object literal extensions

• Promises

• New String methods

• Symbols

• Template strings

• Arrow Functions

ES6 features ship with Node.js by default(v4.2.1)

Page 16: Serverside ES6@Livesense technight

実際手元で触ってて 気になったのは これくらい…

Page 17: Serverside ES6@Livesense technight

• Block scoping • 変数のスコープ、定数化 • letで宣言された変数は、その変数が定義されたブロックにスコープが限定される。

• constで定数化。

Page 18: Serverside ES6@Livesense technight

function varTest() { var x = 31; if (true) { var x = 71; // same variable! console.log(x); // 71 } console.log(x); // 71}

function letTest() { let x = 31; if (true) { let x = 71; // different variable console.log(x); // 71 } console.log(x); // 31}

Page 19: Serverside ES6@Livesense technight

const MY_FAV = 7;

// this will fail silently in Firefox and Chrome (but does not fail in Safari)MY_FAV = 20;

// will print 7console.log("my favorite number is: " + MY_FAV);

// trying to redeclare a constant throws an error const MY_FAV = 20;

// the name MY_FAV is reserved for constant above, so this will also failvar MY_FAV = 20;

Page 20: Serverside ES6@Livesense technight

• Promises • 非同期処理でメソッドを繋げる時、コールバック地獄を回避しつつ、メソッドチェーンで書くことのできる子。

• もともとES6どうこうの前に結構使われてた。

Page 21: Serverside ES6@Livesense technight

function timeout(duration = 0) { return new Promise((resolve, reject) => { setTimeout(resolve, duration); })}

var p = timeout(1000).then(() => { return timeout(2000);}).then(() => { throw new Error("hmm");}).catch(err => { return Promise.all([timeout(100), timeout(200)]);})

Page 22: Serverside ES6@Livesense technight

• Classes (strict mode only) • 目玉商品。JavaScriptで(他の言語と同じような)クラスがかけるよ。

• 最高だよ。もうprototypeとか書かなくて済むよ。 • 書かなくて済むけど、prototypeの糖衣構文です。

Page 23: Serverside ES6@Livesense technight

class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); }}

class Dog extends Animal { speak() { console.log(this.name + ' barks.'); }}

Page 24: Serverside ES6@Livesense technight

• Arrow Functions • 関数型っぽいfunctionの書き方、レキシカルなthis(thisの参照先が、意図に反してグローバルオブジェクトになって、「あれ?このインスタンスのプロパティ更新されないぞ?」「値が入ってないぞ?」というようなことにならない。そのメソッドが呼び出されるオブジェクトの中に閉じている状態)を簡単に扱える。

• というかthisが自動で関数にbindされる

Page 25: Serverside ES6@Livesense technight

function Person(){ this.age = 0;

setInterval(() => { this.age++; // |this| properly refers to the person object }, 1000);}

var p = new Person();

Page 26: Serverside ES6@Livesense technight

• Generators (Function) • イテレーターを簡単に作れる特殊な関数。任意のタイミングで処理を止められる。オブジェクト自身が今どこまで処理を進めたか覚えておき、next()メソッドを使って止めたところから先の処理を再度実行する。

• 特に用事がなかったので僕は使いませんでした。

Page 27: Serverside ES6@Livesense technight

function* anotherGenerator(i) { yield i + 1; yield i + 2; yield i + 3;}

function* generator(i){ yield i; yield* anotherGenerator(i); yield i + 10;}

var gen = generator(10);

console.log(gen.next().value); // 10console.log(gen.next().value); // 11console.log(gen.next().value); // 12console.log(gen.next().value); // 13console.log(gen.next().value); // 20

Page 28: Serverside ES6@Livesense technight

実際に使ってみた例

Page 29: Serverside ES6@Livesense technight

モバイルの勉強がてら、 SwiftでNewsアプリ(笑)を作ってたんですが、 SwiftTaskというSwift版Promise実装

みたいなやつが、マルチリクエスト用途で使いにくくて、 「いっそNodeでAPI置いて、 モバイルが叩くエンドポイントは

1つに統一しよう…どうせ分化する予定だったし」 と思った。

Page 30: Serverside ES6@Livesense technight

その際に、ちょうどNode v4.0.0の io.jsとNode.js統合があったので、

じゃあもうES6に置き換えようと決めた。 (途中まではES5でした)

Page 31: Serverside ES6@Livesense technight

具体例

Page 32: Serverside ES6@Livesense technight

コントローラー部分

Page 33: Serverside ES6@Livesense technight

"use strict";

const _ = require('underscore');const express = require('express');const router = express.Router();const newsCollectionModel = require('../models/newsCollection.model');

router.get('/', (req, res) => { let newsCollection = new newsCollectionModel();

newsCollection.get(req, (items) => { res.json({ response: items }); });});

Page 34: Serverside ES6@Livesense technight

モデル部分

Page 35: Serverside ES6@Livesense technight

class News { constructor(props) { this.title = props.title; this.url = props.url; this.origin = props.origin; this.image_uri = props.image_uri; this.created_at = props.created_at; }

...}

Page 36: Serverside ES6@Livesense technight

_convertNewsModelToObject(items) { return _.flatten(items).map((item) => item.toObject()); }

get(req, cb) { let promises = _.map(urls[req.query.country],

(url) => { return fetch(url, (res) => { return res.body.items }) });

Promise.all(promises) .then((items) => _.flatten(items) ) .then((items) => this._filterFeedlyItemsByImageExistance(items) ) .then((items) => this._createNewsModelCollectionByFeedly(items) ) .then((items) => this._convertNewsModelToObject(items) ) .then((items) => this._sortByCreatedAt(items) ) .then((items) => cb(items), (err) => console.error(err.stack) ); }

Page 37: Serverside ES6@Livesense technight

• Arrow Functionによってコールバック関数に使う文字数を減らせて、視覚的に健康。コントローラーだと多用するので結構変わりますよ。

• 特にモデルクラスだと思いますが、constructorとそれ以外のメソッドを同じclass内の記述としてかけるので、包含関係を意識しやすいです。(prototypeを使って別々に書かなきゃいけない頃とは違い、ちゃんと一個のクラスとして書けてる感じがします)

• underscore.jsとArrow functionの合わせ技で、軽いビジネスロジックなら1行で済ませることができました。(underscore初見の人からすると邪魔っぽいので、ここは要検討)

Page 38: Serverside ES6@Livesense technight

• まとめて複数のAPIをコールするときとか、request用のpromiseインスタンスを作るメソッドを汎用の関数として用意しておく。

• Promise.allで一気に結果を取得した後、then(…).then(…)で、綺麗に値をフィルター/加工できます。

• requireした結果を格納してる変数を誤って更新しないように、全部constで持っておくと安全。

• package.jsonにnodeのバージョンを記載しておけば、herokuで最新版が動かせるので、すぐ試せます。webpackとかいらない。

Page 39: Serverside ES6@Livesense technight

以下要検討の課題

Page 40: Serverside ES6@Livesense technight

• APIから返ってきた値のフィルタリングの処理を、条件ごとに別関数に分けた。

• が、関数の数を減らそうと思うとthenの中身が地獄になり、関数の数を増やせばthenの中身は1行で済んでも、関数が増えすぎて地獄になるか、underscoreで読みにくくなるか、という板挟みだった。苦肉の策としてメソッド名を長くして中身の処理を命名から推測しやすくした。

• 短く書けるからって調子乗ったら死にました。(これはES6ではなく完全に僕の問題です)

Page 41: Serverside ES6@Livesense technight

• modulesがない…実装はよ… • とはいえrequire50倍速という噂もあるし、別にもうmodule.exportsで事足りる。

• Strong ModeかStrict Modeか迷って、中途半端にStrict Mode使ってましたが、Strong Modeで移行すればよかった。。

Page 42: Serverside ES6@Livesense technight

ともあれ、サーバーサイドの 言語として非常に使い勝手がいいです。 expressも軽量だから 書き換えがしやすいです。

Page 43: Serverside ES6@Livesense technight

フロントエンドでES6使うことが 多いですが、ES6のシンタックスだけ 速習したいなら、サーバーサイドから 入ったほうがいいと思います。 Node最新バージョン入れたらすぐ 動くのと、フロントエンド フレームワークの激流に気を取られず、 シンタックスの学習に 集中できるからです。

Page 44: Serverside ES6@Livesense technight

おわり。