哦,代碼……就把它們當成插圖吧javascript
隨着 CPU 從單核變多核,軟件從注重功能到注重體驗,Web 從頁面跳轉方式到 Web2.0 的無刷新加載(AJAX),程序員愈來愈多的接觸多線程和異步。而 Android 的主線程中不容許操做網絡,更是將程序員們推向了異步的深淵。異步深淵產生的主要緣由是回調,這在 nodejs 裏尤爲嚴重。java
// [node.js] doFirstThing(function(err, data) { doSecondThing(data, function(err, data) { doThirdThing(data, function(err, data) { // ... fall down }) }); });
爲了逃離回調的深淵,你們開始想各類辦法來把回調扁平化。node
在 JavaScript 中,Promise(指該類方法而非某個庫)成爲衆多解決方案的佼佼者,併成功被 ES6 採納。git
// [node.js] doFirstThing() .then(doSecondThing) .then(doThirdThing) // .then(...) - continuous .catch(function() { // something wrong });
而 C# 則經過 Task 和 ThreadPool 讓異步編程變得容易。前面談論的 C# 並行計算(Parallel 和 ParallelQuery) 就是基於 Task 的。不過使用 Task.ContinueWith()
和 Parallel.ForEach()
的時候,就會以爲:這不就是 Promise 嗎?程序員
// [csharp] Task.Run(() => { // do first thing and return a data return "first"; }).ContinueWith(task => { // do second thing and return a data return new []{ task.Result, "second" }; }).ContinueWith(task => { // do final thing foreach (string s in task.Result) { Console.WriteLine(s); } }).Wait();
以後 C#5.0 又推出 async/await
方案,將異步代碼寫得像同步代碼同樣,由編譯器來將 async/await
代碼封裝成異步 Task 方式,而不是由人工處理,這大大下降了寫異步程序的門檻。github
// [csharp] private async static Task Process() { string first = await Task.Run(() => "first"); string[] all = await Task.Run(() => { return new [] { first, "second" }; }); await(Task.Run(() => { foreach (string s in all) { Console.WriteLine(s); } })); }
JavaScript 程序員們一邊在等着 ES7 的 async/await
特性,一邊也沒閒着,在 ES6 generator/yield
特性基礎上開發了個 co 出來,提供了相似於 async/await
特性的異步編程方式。編程
// [node.js] var co = require("co"); co(function*() { var first = yield new Promise(function(resolve) { setTimeout(function() { resolve("first"); }, 100); }); var all = yield new Promise(function(resolve) { setTimeout(function() { resolve([first, "second"]) }, 200); }) console.log(all); }); // [ 'first', 'second' ]
不過 co 程序寫起來又要寫 Generator,又要用 yeild,還經常要封裝 Promise,代碼仍然不夠簡潔。目前 async/await 已經在 TypeScript、Babel、Node 7.6+ 等環境中獲得支持,使用 JavaScript 的 async/await 不只能大大簡化代碼,還能下降邏輯思路的複雜度。segmentfault
2018.1.18 更新,由於 async/await 早已進入實踐階段網絡