ecmascript 6 and the node driver

Post on 12-Aug-2015

149 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

ECMAScript 6 and the Node Driver

3

Agenda

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

4

Good Evening

Christian Amor KvalheimDrivers Lead and Node.js driver author

Oviedo, Spain

@christkv

christkv@mongodb.com

http://www.christiankvalheim.com

ES6

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….

ES6 Features

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.

9

Classes

• ES6 Introduces classes

class Cursor { constructor() {}

count() {}}

10

Classes

• ES6 Introduces classes

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

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)

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;}

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.

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); });

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.

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;}

17

Generators + co

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

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)});

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.

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

MongoDB Core

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

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();

24

Mongodb-core

• install

npm install mongodb-core

• Tested on– Node 12.2– IO.js 2.0

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

ES6 Prototype

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

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(); }); });});

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)});

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

30

Classes

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

• Prototype has a minimal API

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); }); });}

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();});

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);});

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)});

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}) }

Performance

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

Release Information

39

Release Information

• Prototype install

npm install mongodb-es6

• Tested on– Node 12.2– IO.js 2.0

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

One MoreThing

41

2.1- alpha with Promises

• 2.1- alpha install

npm install mongodb@2.1-alpha

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

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(); });});

top related