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>