標籤:

如何進行nodejs非同步編程?

看了很多blog,甚至是電子書,大多數人講非同步編程的時候,都只是講原理,最多加上一個小例子。很少人模擬一個實戰場景中的複雜事務和資料庫讀寫,能否給一個較典型的例子?

假如有以下場景:

一個用戶寫了一篇博客提交,nodejs在寫進資料庫的時候,另一個用戶正在註冊成為一個新用戶,我該怎麼樣使用非同步編程使得註冊用戶不必等待太長時間?您可以多給幾種方式。

另外,express在處理路由的時候,不同的請求被分發至不同的方法處理,有的是耗時任務,有的不是,我怎麼樣通過非同步編程處理這麼多請求之間的關係,而使得用戶等待時間最短?

盼望有例子,有講解。謝謝!

-------------------------------------------------------------------------------------------------------------------------------

感謝saviio的回答。

ajax和settimeout方法是javascript原生的方法,無法看見是怎樣實現的,但是就是可以用。那麼,自己如何實現呢?

還有,如果使用express,routes.js文件中通常要有以下配置

app.get(/userList, user.userList); app.get(/user/addUser, user.addUser); app.get(/user/userManager, user.userManager);其實可以更多更長,有人請求userList,user.userList方法馬上就去處理了,這時候,又來了一個/user/addUser的請求。如果user.userList需要執行的時間比較長,需要addUser的用戶就不得不等待,而我,好像沒有辦法,(( ╯□╰ )能理解我的心情吧)。

這樣的場景,我該怎樣非同步編程,使得addUser的用戶不必等到user.userList方法執行完了再開始?


更新下,我之所以讓您玩一下AJAX,是希望您體驗一下非同步,並不是希望您了解AJAX這機制的實現方法,因為AJAX是一個特別典型且簡單的非同步場景,比如:

執行某個函數 -&> 執行語句A,B,C,D -&> 在D語句發起非同步請求,同時向引擎註冊一個回調事件 -&> 執行E,F,G -&>退出函數塊 ,引擎Loop...Loop...Loop,此時非同步的請求得到了Response,之前註冊的回調被執行。

@VILIC VANE 也提到了,實際上Node.js主要是為了應對主流web app存在大量I/O等待而CPU閑置的場景所衍生的解決方案,而在架構上,它的後端有一個底層的worker封裝,每當你有一個諸如addUser這樣的I/O操作時,它們都會被交由worker去執行從而達到讓出儘快讓出當前函數的執行權的目的,在向引擎註冊完回調後,內部會通過事件輪詢去檢查該I/O事件的句柄,當句柄顯示該事件操作完成後,則註冊的回調則被執行。

所以,假設有人(按題設,簡化一下場景,有且只有2個人)同時請求addUser(A)和userList(B),B的請求會在執行完A的請求內部所有同步代碼後被執行,而哪怕worker此時仍然在進行addUser 這一 I/O操作,用戶B也並不會被引擎掛起或者等待。這就是為什麼Node.js單節點卻一樣可以擁有高負載能力的原因。

至於什麼樣的代碼是非同步的,你看看node文檔里fs模塊的使用方法就知道了,大概的形式就是如下這種。

module.method( args [,callback] )

當然還有一種比較極端的情況,假設您使用的資料庫是山寨的,驅動是基於同步實現的,那麼B就該等多久等多久把,樹蔭底下喝杯茶,下個棋,和後面的C,D,E,F,G打個招呼唄~~~

======================================================================

我推薦您先去玩一下前端的AJAX了解一下 非同步編程方式,體驗一下非同步的「感覺」,然後看一本叫《JavaScript非同步編程》的書。

Node.js 是一款基於Event-driven的模型構建的Framework,它典型的特徵就是通過內置的事件輪詢來調度事件,通常來說node.js的資料庫驅動都是基於非同步實現的,所以在實際情況中,A提交博客和B註冊用戶這兩個請求是可以同時由Node.js 來handle,並按照實際操作的處理事件分別調度給予瀏覽器響應。

當然,假設您在業務代碼里寫了一個耗時很久的同步代碼(比如直接寫一個while(true)的loop,Node就死了),由於JavaScript本身單線程的限制,所以整個App就會被block住,後續的事件/程序只有等到該段代碼執行完成之後才會被處理,這也是為什麼我們通常不建議在Node.js層做大規模計算(JS本身的計算效率太低,會導致Node吞吐量會大大降低),而傾向由C++的拓展去實現。


在只有一個請求的情況下非同步不會減少用戶的等待時間. 而是在處理 IO 等耗時不耗 CPU 的過程的時候, 可以繼續接收處理請求, 不會 block 整個進程. 也就是說, 同一個進程, 可以同時處理來自多個用戶的請求 (如果這些請求都是以 IO 為主). 其他情況, 如 PHP, 需要同時處理幾個請求就要幾個線程.

你的情況只需要客戶端同時發起兩個請求就可以了.


問:如何進行nodejs非同步編程?

答:難道你還可以用nodejs編寫同步的程序?請問怎樣實現的?

問:一個用戶寫了一篇博客提交,nodejs在寫進資料庫的時候,另一個用戶正在註冊成為一個新用戶,我該怎麼樣使用非同步編程使得註冊用戶不必等待太長時間?

答:兩個操作互相完全沒有關係,用戶完全不需要等待什麼。

。。。。。。

後面的答不下去了。樓主明顯是對js了解的太粗淺了。這種水平請先惡補一下js的基礎知識。建議當你可以完全理解並且純熟運用『閉包』這個東西的時候,才能寫nodejs。


一個用戶寫了一篇博客提交,nodejs在寫進資料庫的時候,另一個用戶正在註冊成為一個新用戶,我該怎麼樣使用非同步編程使得註冊用戶不必等待太長時間?您可以多給幾種方式。

另外,express在處理路由的時候,不同的請求被分發至不同的方法處理,有的是耗時任務,有的不是,我怎麼樣通過非同步編程處理這麼多請求之間的關係,而使得用戶等待時間最短?

你提的這兩個問題,就我所知,根本辦不到,在nodejs編碼方面,沒有什麼可操作的空間,如果錯,求打臉。

補充的問題,也無解,就所描述來看,不妨把userList看錯是計算密集型任務,NODEjs官方文檔都說了,nodejs不適合作計算密集型開發。

我感覺題主對web的基本架構,同步/非同步的概念不是很清楚。

你應該先了解下web高並發下,用同步方式實驗可能導致的問題,這樣會對非同步有更深的了解。

就是幾個關鍵字,多線程,資源搶佔,IO阻塞,線程切換開銷。

nodejs非同步式開發,就是為了避免在高並發現同步會產生的問題。

你所提的幾個問題,相對這些同步的大問題來說,分好適用場景,實際上根本不算事,你問的這些,不在非同步設計的考慮之內,很難碰上,最好避免,碰上,那就認了吧。


題主需要補充一下非同步和同步的基礎知識。

nodejs的IO操作都是非同步的,打一個簡單的比方:

1. 把用戶許可權存到資料庫

2. 把用戶許可權從資料庫取出來

一般的後台語言(比如java):

這兩步操作一般寫作同步操作,也就是說代碼按照順序執行這2個方法就好。

如果是nodejs:

先執行函數1,然後在函數1的回調函數中調用函數2。

如果java的寫法,就會出現存和取的操作請求同時發起,最終函數2 的結果可能有數據,也可能沒數據。

至於你說的第二段中的不然註冊用戶等太久的說法是不存在的,這不是非同步和同步的問題,這是資料庫連接並發的問題,一般是通過資料庫連接池搞定的。


推薦閱讀:

Node.js+Node-webkit的開發模式前景如何?
Node.js被高估了嗎?
如何評價 Node.js 8.0 ?
深JS(2015 JS中國開發者大會)有哪些女生參加?

TAG:Nodejs | 非同步 |