Node.js的異步是整個學習Node.js過程當中重中之重。前端
1)異步流程控制學習重點vue
2)Api寫法:Error-first Callback 和 EventEmitternode
3)中流砥柱:Promisejquery
4)終極解決方案:Async/Awaitgit
.Node.js SDK裏callback寫法必須會的。github
Node.js學習重點: Async函數與Promisenpm
1.中流砥柱:Promiseapi
2.終極解決方案:Async/Awaitpromise
定義錯誤有限的回調寫法只須要注意2條規則便可:併發
下面讓咱們看一下調用函數示例,Node.js文檔例最常採用下面這樣的回調方式:
function(err,res){ //process the error and result }
這裏的 callback 指的是帶有2個參數的函數:「err」和「res」 。語義上講,非空的"err"至關於程序異常;而空的「err」至關於能夠正常返回結果「res」,無任何異常。
事件模塊是 Node.js內置的對觀察者模式「發佈/訂閱」(publish/subscribe)的實現,經過 EventEmitter屬性,提供了一個構造函數。該構造函數的實例具備 on 方法,能夠用來監聽指定事件,並觸發回調函數。任意對象均可以發佈指定事件,被 EventEmitter 實例的 on方法監聽到。
在node6以後,能夠直接使用require('events')類
var EventEmitter = require('events') var util = require('util') var MyEmitter = function(){ } util.inherits(MyEmitter,EventEmitter) const myEmitter = new MyEmitter(); myEmitter.on('event',(a,b)=>{ console.log(a,b,this) // Prints: a b {} }) myEmitter.emit('event','a','b')
和jquery、vue 裏的Event 是很是相似的。並且前端本身也有EventEmitter。
API 是應用程序接口 Application Programming interface的簡稱。從Node.js異步原理,咱們能夠知道,核心在於Node.js SDK中API調用,而後交由EventLoop(Libuv)去執行,因此咱們必定要熟悉Node.js的API操做。
Node.js的API都是異步的,同步的函數是奢求,要查API文檔,在高併發場景下慎用。
筆者推薦使用 Desh和 Zeal查看離線文檔,對api理解會深刻不少,比IDE輔助要好,能夠有效避免離開IDE就不會寫代碼的窘境。
回調地獄
Node.js由於採用了錯誤優先的回調風格寫法,致使sdk裏導出都是回調函數,就會特別痛苦,常常會出現回調裏嵌套回調的問題,你們都很是厭煩這種寫法,稱之爲 Callback Hell,即回調地獄。一個經典的例子來自著名的Promise模塊 q 文檔裏。
step1(function(value1){ step2(value1,function(value2){ step3(value2,function(value3){ step4(value3,function(){ // Do something with value4 }); }); }); });
這裏只是作4步,嵌套了4層回調,若是更多步驟呢?不少新手淺嘗輒止,到這兒就望而卻步,粉轉黑。這明顯不夠成熟,起碼你要看看它的對應解決方案吧!
Promise最先也是在commonjs社區提出來的,當時提出了不少規範。比較接受的是promise/A規範。後來人們在這個基礎上,提出了promise/A+規範,也就是實際上如今的業內推行的規範。ES6 也是採用的這種規範。
Promise意味着[許願|承諾]一個尚未完成的操做,但在將來會完成的。與Promise最主要的交互方法是經過將函數傳入它的then方法從而獲取得Promise最終的值或Promise最終拒絕(reject)的緣由。要點有三個:
var promise = new Promise(function(resolve, reject) { //do a thing,possibly async, then... if (/*everything turned out fine*/) { resolve("Stuff worked!") } else { reject(Error("It broke")) } })
每一個Promise定義都是同樣的,在構造函數裏傳入一個匿名函數,參數是resolve和reject,分別表明成功和失敗時候的處理。
promise.then(function(text){ console.log(text)//Stuff worked! return Promise.reject(new Error('我是故意的')) }).catch(function(err){ console.log(err) })
它的主要交互方式是經過then函數,若是Promise成功執行resolve了,那麼它就會將resolve的值傳給最近的then函數,做爲它的then函數的參數。若是出錯reject,那就交給catch來捕獲異常就行了。
Promise 的最大優點是標準化,各種異步工具庫都按照統一規範實現,即便是async函數也能夠無縫集成。因此用 Promise 封裝 API 通用性強,用起來簡單,學習成本低。在async函數普及以前,絕大部分應用都是採用Promise來作異步流程控制的,因此掌握Promise是Node.js學習過程當中必需要掌握的重中之重。
Bluebird是 Node.js 世界裏性能最好的Promise/a+規範的實現模塊,Api很是齊全,功能強大,是原生Promise外的不二選擇。
好處以下:
在學習Node.js過程當中,對於Promise瞭解多深刻都不過度。
推薦學習資料
Async/Await是異步操做的終
極解決方案,Koa 2在node 7.6發佈以後,立馬發佈了正式版本,而且推薦使用async函數來編寫Koa中間件。
這裏給出一段Koa2應用裏的一段代碼:
exports.list = async(ctx, next)=>{ try { let students = await Student.getAllAsync(); await ctx.render('students/index',{ students : students }) } catch (err) { return ctx.api_error(err) } }
它作了3件事兒
是否是很是簡單,如今Eggjs裏也都是這樣同步的代碼。
const pkgConf = require('pkg-conf') async function main(){ const config = await pkgConf('unicorn'); console.log(config.ranbow); //true } main()
變態寫法:
const pkgConf = require('pkg-conf'); (async ()=> { const config = await pkgConf('unicorn') console.log(config.ranbow) //true })()
const Promise = require('bluedbird'); const fs = Promise.promisifyAll(require("fs")); async function main(){ const contents = await fs.readFileAsync("myfile.js","utf8") console.log(contents) } main()
const co = require('co') const Promise = require('bluedbird') const fs = Promise.promisifyAll(require("fs")) async function mian(){ const contents = co(function* () { var result = yield fs.readFileAsync("myfile.js","utf8") return result; }) console.log(contents) } main()
要點:
由上面3種基本用法能夠推出Async 函數要點以下:
這部分共講了4個小點,都是極其直接的必須掌握的知識點。
先用明白,而後再去閱讀Node.js源碼,而後探尋libuv併發機制。不少人買了樸大的《深刻淺出Node.js》一書,看了以後仍是不太會用,不是書寫的很差,而是步驟不對。
迷茫時學習Node.js最好的方法
Node.js 編寫的包管理器 npm 已成爲開源包管理了領域最好的生態,直接到2017年10月份,有模塊超過47萬,每週下載量超過32億次,每月有超過700萬開發者使用npm。如今早已經超過60萬個模塊了。
這裏就不一一舉例了,給出一個迷茫時學習Node.js最好的方法吧!
"天天看10個npm模塊"
對於學習Node.js迷茫的人來講,這是最好的方式,當你不知道如何作的時候,就要向前(錢)看,你要知道積累哪些技能對之後有好處。對於學習Node.js必經之路,必定是要掌握不少模塊用法,並從中汲取技巧、思路、設計思想的。與其不知道學什麼,爲何不天天積累幾個技巧呢?
推薦一個repo即 https://github.com/parro-it/awesome-micro-npm-packages 小型庫集合,一天看十個不是夢!
更多討論 https://zhuanlan.zhihu.com/p/29625882
此爲學習node的學習筆記,爲了本身學習查閱,轉自狼叔的教程,若是侵權請聯繫我刪除
閱讀原文