ecmascript 6 and the node driver

43

Upload: mongodb

Post on 12-Aug-2015

149 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: ECMAScript 6 and the Node Driver
Page 2: ECMAScript 6 and the Node Driver

ECMAScript 6 and the Node Driver

Page 3: ECMAScript 6 and the Node Driver

3

Agenda

• ES6• ES6 Features• MongoDB Core• ES6 Prototype• Performance

Page 4: ECMAScript 6 and the Node Driver

4

Good Evening

Christian Amor KvalheimDrivers Lead and Node.js driver author

Oviedo, Spain

@christkv

[email protected]

http://www.christiankvalheim.com

Page 5: ECMAScript 6 and the Node Driver

ES6

Page 6: ECMAScript 6 and the Node Driver

6

ES6

• ES6 Is a fundamental rethink of the JavaScript language• Introduces a lot of new features

– Iterators– Generators– Proxies– Promises– Classes– and much more….

Page 7: ECMAScript 6 and the Node Driver

ES6 Features

Page 8: ECMAScript 6 and the Node Driver

8

Classes

• Classes are syntactic sugar on top of JavaScript existing prototype based inheritance.

• Classes do not introduce a new Object Oriented inheritance model.

• Classes simplify the code and provides a clearer syntax for prototype based inheritance.

Page 9: ECMAScript 6 and the Node Driver

9

Classes

• ES6 Introduces classes

class Cursor { constructor() {}

count() {}}

Page 10: ECMAScript 6 and the Node Driver

10

Classes

• ES6 Introduces classes

class SpecialCursor extends Cursor { constructor() { super(); }}

Page 11: ECMAScript 6 and the Node Driver

11

Iterators

• Iterators are created using a protocol allowing JavaScript objects to define or customize their iteration behavior.

• Arrays in ES6 are now iterators and can be used in the new for-of construct.

• An object is an Iterator when it implements a next() method that returns an object with two properties.– done (boolean)– value (any JavaScript value)

Page 12: ECMAScript 6 and the Node Driver

12

Iterators

class Next { constructor(value) { this.value = value || 0; }}

Next.prototype[Symbol.iterator] = function() { var cur = this.value;

return { next() { return {done: false, value: cur++} } } }

for(var n of new Next()) { if(n == 1000) break;}

Page 13: ECMAScript 6 and the Node Driver

13

Promises

• A Promise is an object used for deferred and asynchronous computations.

• A promise can either be fulfilled with a value or rejected.• Promises can be chained using then.• Execute n promises using Promise.all.• Very useful to orchestrate asynchronous operations.• Allows for easier reasoning of call chains.

Page 14: ECMAScript 6 and the Node Driver

14

Promises

var p2 = new Promise(function(resolve, reject) { resolve(2);});

p2.then(function(value) { assert(2, value);});

var promise = Promise.resolve(3);Promise.all([true, promise]) .then(function(values) { console.log(values); });

Page 15: ECMAScript 6 and the Node Driver

15

Generators

• A Generator is a function that can be exited, and then later re-entered.

• The context of the function is saved across re-entrances.• Calling a Generator function returns an iterator object.• Calling next on the iterator executes the function until the

first yield is encountered.

Page 16: ECMAScript 6 and the Node Driver

16

Generators

class Next { constructor(value) { this.value = value || 0; }}

Next.prototype[Symbol.iterator] = function*() { var cur = this.value;

while(true) { yield cur++; }}

for(var n of new Next()) { if(n == 1000) break;}

Page 17: ECMAScript 6 and the Node Driver

17

Generators + co

• co library– Runs a generator to the end– Expects to yield on promises– Simplifies the syntax for programming

Page 18: ECMAScript 6 and the Node Driver

18

Generators + co

var co = require('co'), assert = require('assert');

var p1 = new Promise(function(resolve, reject) { resolve(2);});

co(function*() { var value = yield p1; assert.equal(2, value);}).catch(function(err) { console.dir(err)});

Page 19: ECMAScript 6 and the Node Driver

19

Proxies

• Proxies allows a user to override fundamental behaviors of an object– Property lookup– Assignment– Function calls– Enumeration

• Proxies is close to method_missing in ruby.• Proxies can lead to slow execution if in critical code path.

Page 20: ECMAScript 6 and the Node Driver

20

Proxies

var handler = { get: function(target, name){ return name in target ? target[name] : 37; }};

var p = new Proxy({}, handler);p.a = 1;p.b = undefined;

console.log(p.a, p.b); // 1, undefinedconsole.log('c' in p, p.c); // false, 37

Page 21: ECMAScript 6 and the Node Driver

MongoDB Core

Page 22: ECMAScript 6 and the Node Driver

22

MongoDB Core

• MongoDB Core is a low level driver wrapping the wire protocol and authentication– No abstractions

• MongoDB Core was developed to allow for people to more easily write– ODMs (Object Document Modeling)– Driver Wrappers– Tools/Frameworks

Page 23: ECMAScript 6 and the Node Driver

23

Simple Example

var Server = require('mongodb-core').Server;

// Attempt to connectvar server = new Server({ host: 'localhost', port: 27017 })

// Add event listenersserver.on('connect', function(server) { // Execute the command server.command("system.$cmd" , {ismaster: true}, function(err, result) { server.destroy(); });});

server.connect();

Page 24: ECMAScript 6 and the Node Driver

24

Mongodb-core

• install

npm install mongodb-core

• Tested on– Node 12.2– IO.js 2.0

• https://github.com/christkv/mongodb-core

Page 25: ECMAScript 6 and the Node Driver

ES6 Prototype

Page 26: ECMAScript 6 and the Node Driver

26

ES6 Prototype

• Prototype aims to explore the ES6 space to improve the usability of the driver.– Leverage only the features of ES6 that improves

productivity– Ensure no significant performance degradation

happens in the transition from ES5 to ES6

Page 27: ECMAScript 6 and the Node Driver

27

FROM

var MongoClient = require(‘mongodb’).MongoClient, assert = require(‘assert’);

MongoClient.connect(‘mongodb://localhost:27017/test’ , function(e, d) { assert.equal(null, e); var c = d.collection(‘test1’); c.insertOne({a:1}, function(e, r) { assert.equal(null, e);

c.find({}).toArray(function(e, docs) { assert.equal(null, e); assert.equal(1, docs.length); d.close(); }); });});

Page 28: ECMAScript 6 and the Node Driver

28

TO

var MongoClient = require(’mongodb-es6').MongoClient, co = require(‘co’);

co(function* () { var client = yield new MongoClient('mongodb://localhost:27017/test', {}).connect()

try { var result = yield client['tests']['cursors'].insertOne({a:2}); } catch(err) {};

var docs = yield client['tests']['cursors'].find({}).toArray();}).catch(function(err) { console.dir(err)});

Page 29: ECMAScript 6 and the Node Driver

29

ES6 Driver Design

• Driver uses MongoDB Core as it’s bases.• Driver leverages the following features of ES6

– Classes– Promises

• Forward compatible with co• Forward compatible with ES7 async/await

– Proxies

Page 30: ECMAScript 6 and the Node Driver

30

Classes

• Prototype has classes for– Db– Collection– Cursor– AggregationCursor– CommandCursor– MongoClient

• Prototype has a minimal API

Page 31: ECMAScript 6 and the Node Driver

31

Promises

• Prototype returns a Promise for all asynchronous methods, no callbacks.command(cmd) { var self = this;

return new this.options.promise(function(resolve, reject) { self.topology.command(f('%s.$cmd', self.name), cmd, function(err, r) { if(err) reject(err); else resolve(r); }); });}

Page 32: ECMAScript 6 and the Node Driver

32

Promises

• Prototype returns standard ES6 promises• Bring Your Own Promises (BYOP)

var MongoClient = require(’mongodb-es6').MongoClient , P = require("bluebird");

co(function* () { var client = yield new MongoClient('mongodb://localhost:27017/test’)

.promiseLibrary(P).connect();});

Page 33: ECMAScript 6 and the Node Driver

33

Promises + Iteration

• Iterating a cursor is completely different from 2.x

var MongoClient = require(’mongodb-es6').MongoClient , P = require("bluebird");

co(function* () { var client = yield new MongoClient('mongodb://localhost:27017/test’)

.promiseLibrary(P).connect(); var cursor = client[‘tests’][‘docs’].find({});

while(yield cursor.hasNext()) { console.dir(yield cursor.next()); }}).catch(function(err) { console.dir(err);});

Page 34: ECMAScript 6 and the Node Driver

34

Proxies

• Prototype uses proxies to allow for simpler access to databases allowing you to do.var MongoClient = require(’mongodb-es6').MongoClient, co = require(‘co’);

co(function* () { var client = yield new MongoClient('mongodb://localhost:27017/test', {}).connect();

var testsDb = yield client['tests’]; var cursorsCollection = yield testsDb['cursors’]}).catch(function(err) { console.dir(err)});

Page 35: ECMAScript 6 and the Node Driver

35

Proxies Gotchas

• Proxies come with some performance implications.• Proxies are inherently poison to the way V8 JITs into

stable classes as a proxy wrapped instance can be x possible classes forcing de-optimizations.for(var i = 0; i < 10; i++) { yield client[‘tests’][‘docs’].insertOne({a:1});}

var col = client[‘tests’][‘docs’];for(var i = 0; i < 10; i++) { yield col.insertOne({a:1}) }

Page 36: ECMAScript 6 and the Node Driver

Performance

Page 37: ECMAScript 6 and the Node Driver

37

Performance

2.0 (IO 2.0) simple_100_document_toArray

Average 0.414 ms

Standard Deviation 0.498 ms

ES6 (IO 2.0) simple_100_document_toArray

Average 0.415 ms

Standard Deviation 0.501 ms

Page 38: ECMAScript 6 and the Node Driver

Release Information

Page 39: ECMAScript 6 and the Node Driver

39

Release Information

• Prototype install

npm install mongodb-es6

• Tested on– Node 12.2– IO.js 2.0

• https://github.com/christkv/mongodb-es6

Page 40: ECMAScript 6 and the Node Driver

One MoreThing

Page 41: ECMAScript 6 and the Node Driver

41

2.1- alpha with Promises

• 2.1- alpha install

npm install [email protected]

• https://github.com/mongodb/node-mongodb-native

Page 42: ECMAScript 6 and the Node Driver

42

Simple 2.1-alpha Example

var MongoClient = require(’mongodb'), Promise = require('bluebird');

MongoClient.connect(configuration.url(), { promiseLibrary: Promise}).then(function(db) { var promise = db.collection('test').insert({a:1}); test.ok(promise instanceof Promise);

promise.then(function() { db.close(); test.done(); });});

Page 43: ECMAScript 6 and the Node Driver