1.2 ES2015 Promise
所謂 Promise,就是一個(gè)對(duì)象,用來(lái)傳遞異步操作的消息。它代表了某個(gè)未來(lái)才會(huì)知道結(jié)果的事件(通常是一個(gè)異步操作),并且這個(gè)事件提供統(tǒng)一的 API,可供進(jìn)一步處理。

一個(gè) Promise 一般有3種狀態(tài):
1.pending : 初始狀態(tài), 不是 fulfilled ,也不是 rejected .
2.fulfilled : 操作成功完成.
3.rejected : 操作失敗.
一個(gè) Promise 的生命周期如下圖:

下面我們看一段具體代碼:

asyncFunction 這個(gè)函數(shù)會(huì)返回 Promise 對(duì)象, 對(duì)于這個(gè) Promise 對(duì)象,我們調(diào)用它的 then 方法來(lái)設(shè)置 resolve 后的回調(diào)函數(shù), catch 方法來(lái)設(shè)置發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。
該 Promise 對(duì)象會(huì)在 setTimeout 之后的 16ms 時(shí)被 resolve , 這時(shí) then 的回調(diào)函數(shù)會(huì)被調(diào)用,并輸出’Async Hello world’ 。
在這種情況下 catch 的回調(diào)函數(shù)并不會(huì)被執(zhí)行(因?yàn)?Promise 返回了 resolve), 不過(guò)如果運(yùn)行環(huán)境沒(méi)有提供 setTimeout 函數(shù)的話,那么上面代碼在執(zhí)行中就會(huì)產(chǎn)生異常,在 catch 中設(shè)置的回調(diào)函數(shù)就會(huì)被執(zhí)行。

小結(jié)
如果是編寫(xiě)一個(gè) SDK 或 API,推薦使用傳統(tǒng)的 callback 或者 Promise,不使用 generator 的原因是:
generator 的出現(xiàn)不是為了解決異步問(wèn)題
使用 generator 是會(huì)傳染的,當(dāng)你嘗試 yield 一下的時(shí)候,它要求你也必須在一個(gè) generator function 內(nèi)
看來(lái)學(xué)習(xí) Promise 是水到渠成的事情。
2. Express、Koa 的異常處理

一個(gè)友好的錯(cuò)誤處理機(jī)制應(yīng)該滿足三個(gè)條件:
對(duì)于引發(fā)異常的用戶,返回 500 頁(yè)面
其他用戶不受影響,可以正常訪問(wèn)
不影響整個(gè)進(jìn)程的正常運(yùn)行
下面我們就以這三個(gè)條件為原則,具體介紹下 Express、Koa 中的異常處理。
2.1 Express 異常處理
在 Express 中有一個(gè)內(nèi)置的錯(cuò)誤處理中間件,這個(gè)中間件會(huì)處理任何遇到的錯(cuò)誤。
如果你在 Express 中傳遞了一個(gè)錯(cuò)誤給 next() ,而沒(méi)有自己定義的錯(cuò)誤處理函數(shù)處理這個(gè)錯(cuò)誤,這個(gè)錯(cuò)誤就會(huì)被 Express 默認(rèn)的錯(cuò)誤處理函數(shù)捕獲并處理,而且會(huì)把錯(cuò)誤的堆棧信息返回到客戶端,這樣的錯(cuò)誤處理是非常不友好的。
還好我沒(méi)可以通過(guò)設(shè)置 NODE_ENV 環(huán)境變量為 production ,這樣 Express 就會(huì)在生產(chǎn)環(huán)境模式下運(yùn)行應(yīng)用,生產(chǎn)環(huán)境模式下 Express 不會(huì)把錯(cuò)誤的堆棧信息返回到客戶端。
在 Express 項(xiàng)目中可以定義一個(gè)錯(cuò)誤處理的中間件用來(lái)替換 Express 默認(rèn)的錯(cuò)誤處理函數(shù):

在所有其他 app.use() 以及路由之后引入以上代碼,可以滿足以上三個(gè)友好錯(cuò)誤處理?xiàng)l件,是一種非常友好的錯(cuò)誤處理機(jī)制。
2.2 Koa 異常處理
我們以 Koa 1.x 為例,看代碼:

把上面的代碼放在所有 app.use() 函數(shù)前面,這樣基本上所有的同步錯(cuò)誤均會(huì)被try{} catch(err){} 捕獲到了,具體原理大家可以了解下 Koa 中間件的機(jī)制。
2.3 未捕獲的異常 uncaughtException
上面的兩種異常處理方法,只能捕獲同步錯(cuò)誤,而異步代碼產(chǎn)生的錯(cuò)誤才是致命的, uncaughtException 錯(cuò)誤會(huì)導(dǎo)致當(dāng)前的所有用戶連接都被中斷,甚至不能返回一個(gè)正常的 HTTP 錯(cuò)誤碼,用戶只能等到瀏覽器超時(shí)才能看到一個(gè) no data received 錯(cuò)誤。
這是一種非常野蠻粗暴的異常處理機(jī)制,任何線上服務(wù)都不應(yīng)該因?yàn)?uncaughtException 導(dǎo)致服務(wù)器崩潰。