Werner Vogels在主题演讲上简要叙述了Lambda设计思路的由来。javascript
Vogels首先抛出一个问题:什么是云计算的根本(primitives)?html
答案:云计算是一个执行环境。java
Vogels再抛出第二个问题:什么是应用的根本?node
答案:函数(functions,即业务逻辑的载体)+数据(data,即跟业务相关的输入与输出),以及这二者之间的交互——即事件(events。常见的事件如增长、变动、删除等)。react
换言之,对于一个应用来讲,除了functions、data、events这三个东西是根本以外,其余不管什么代码和框架,无非都是胶水或者UI罢了。es6
既然如此,理想的状况是用最少的时间写胶水,将作多的时间投入到应用的核心当中。npm
而最多见的胶水代码,就是触发器(trigger):当发生一个事件(event)时,执行某个函数(function),输出新的数据(data)。Vogels以Excel表单为例:在一个表单当中,一个单元格数值的变动,触发总和列对应单元格数值的变动,就是一个事件触发函数将新的变量归入计算得出新的数值的过程。这个过程是自动的,还能够是并发的,即一处变动同时触发多个函数。编程
在编程语言中,函数(functions)+数据(data)+事件(events)的有机组合就是类(class)。在ES6中、类(class)的主体只能包含方法,不能包含数据属性。从通常的编程理论中也明确阐述,类变量或称为数据(data)应该用访问方法(如getter和setter)进行封装,以保证数据的完整性和一致性。跨域
Vogels以Excel表单举例,说明当数据(data)变化后,触发函数执行;更多人会用react的stats举例,当数据(data)变化后,触发DomTree刷新。这是受数据驱动编程的影响?我只能理解为流派之争。怎么着你都得写个listener吧?listener也是函数!
回到正题,既然应用的本质都是一个类(class),固然最好的API接口也是一个类(class)。当类变量或称数据(data)只能经过类函数访问时,正好符合ES6中的类(class)定义。ES6中的类(class)只包含类函数(functions),其中一部分函数(functions)被其它程序直接调用,另外一个部分函数(functions)被事件激活调用。
你new与不new,API单例对象都在那里,不增也不减。
这里借用scala语言中对单例对象的叙述:“类和单例对象间的一个差异是,单例对象不带参数,而类能够。由于你不能用new关键字实例化一个单例对象,你没机会传递给它参数。每一个单例对象都被做为由一个静态变量指向的虚构类:synthetic class的一个实例来实现,所以它们与Java静态类有着相同的初始化语法。Scala程序特别要指出的是,单例对象会在第一次被访问的时候初始化。”
与Java语言同样,在ES6中也没有单例对象(singleton object)的定义方法。而要记住的是对每个调用接口的程序而言,实现的接口(API)类是个单例对象。
跨域访问 - 支持
浏览器中调用 - 支持
nodejs中调用 - 支持
class HelloWorld { constructor() { this.greeting = 'Hello World!'; } welcome(callback) { callback(null, this.greeting); } } export default HelloWorld;
使用babel转成ES5
$ babel HelloWorld.es6 -o HelloWorld.js
如今要把你写好的class发布出去了!
# npm install nodeway -g # nodeway --class HelloWorld.js --host 0.0.0.0 --port 8080 --docs . &
这句的意思是启动一个Web Server,把HelloWorld.js发布出去。好了,如今剩下的就是测试了。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>HelloWorld</title> <script type="text/javascript" src="/HelloWorld.js"></script> </head> <body> <script> var cb = function(err, greeting) { document.write(greeting+'<br/>'); }; var api = new HelloWorld.default; api.welcome(cb); </script> </body> </html>
用浏览器访问你写的这个index.html文件,就能够看到你发布成功了。
class HelloWorld { constructor() { this.greeting = 'Hello World!'; // 如下是新添加代码,6秒发一个'again'事件 this.events = {}; setInterval(() => { this.emit && this.emit('again', null, this.greeting); }, 6000); // 以上是新添加代码 } // 如下是新添加代码 on(eventName, fn) { this.events[eventName] = fn; } emit() { let args = Array.from(arguments), fn = this.events[args.shift()]; fn && fn.apply(this, args); } // 以上是新添加代码 welcome(callback) { callback(null, this.greeting); } } export default HelloWorld;
class HelloWorld { constructor() { this.greeting = 'Hello World!'; // 如下是新添加代码,6秒发一个'again'事件 this.events = {}; setInterval(() => { this.emit && this.emit('again', null, this.greeting); }, 6000); // 以上是新添加代码 } // 如下是新添加代码 on(eventName, fn) { this.events[eventName] = fn; this.constructor.prototype.emit || (this.constructor.prototype.emit = function() { let args = Array.from(arguments), fn = this.events[args.shift()]; fn && fn.apply(this, args); }); } // 以上是新添加代码 welcome(callback) { callback(null, this.greeting); } } export default HelloWorld;
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>HelloWorld</title> <script type="text/javascript" src="/HelloWorld.js"></script> </head> <body> <script> var cb = function(err, greeting) { document.write(greeting+'<br/>'); }; var api = new HelloWorld.default; api.welcome(cb); // 如下是新添加代码 api.on('again', cb); // 以上是新添加代码 </script> </body> </html>