Node.js的process.nextTick(callback)理解

來源:互聯網
上載者:User

標籤:style   blog   http   io   ar   color   os   使用   sp   

 

Node.js是單線程的,基於事件迴圈,非阻塞 IO的。事件迴圈中使用一個事件隊列,在每個時間點上,系統只會處理一個事件,即使電腦有多個CPU核心,也無法同時並行的處理多個事件。因此,node.js適合處理I/O型的應用,不適合那種CPU運算密集型的應用。在I/O型的應用中,給每一個輸入輸出定義一個回呼函數,node.js會自動將其加入到事件輪詢的處理隊列裡,當I/O操作完成後,這個回呼函數會被觸發,系統會繼續處理其他的請求。

在這裡用debuggable.com上的那個文章中的一段比喻來講,非常容易理解。如下:

我們寫的js代碼就像是一個國王,而nodejs給國王提供了很多僕人。早上,一個僕人叫醒了國王,問他有什麼需要。國王給他一份清單,上面列舉了所有需要完成的任務,然後睡回籠覺去了。當國王回去睡覺之後,僕人才離開國王,拿著清單,給其它的僕人一個個布置任務。僕人們各自忙各自的去了,直到完成了自己的任務後,才回來把結果稟告給國王。國王一次只召見一個人,其它的人就在外面排著隊等著。國王處理完這個結果後,可能給他布置一個新的任務,或者就直接讓他走了,然後再召見下一個人。等所有的結果都處理完了,國王就繼續睡覺去了。直接有新的僕人完成任務後過來找他。這就是國王的幸福生活。

process.nextTick(callback)

功能:在事件迴圈的下一次迴圈中調用 callback 回呼函數。效果是將一個函數延遲到代碼書寫的下一個同步方法執行完畢時非同步方法呼叫的事件回呼函數開始執行時;與setTimeout(fn, 0) 函數的功能類似,但它的效率高多了。

基於node.js的事件迴圈分析,每一次迴圈就是一次tick,每一次tick時,v8引擎從事件隊列中取出所有事件依次進行處理,如果遇到nextTick事件,則將其加入到事件隊尾,等待下一次tick到來時執行;造成的結果是,nextTick事件被順延強制;以下是nextTick源碼

從這幾行代碼中,我們可以看出很多資訊:

  1. nextTick的確是把某任務放在隊列的最後(array.push)
  2. nodejs在執行任務時,會一次性把隊列中所有任務都拿出來,依次執行
  3. 如果全部順利完成,則刪除剛才取出的所有任務,等待下一次執行
  4. 如果中途出錯,則刪除已經完成的任務和出錯的任務,等待下次執行
  5. 如果第一個就出錯,則throw error

下面看一下應用情境(包含計算密集型操作,將其進行遞迴處理,而不阻塞進程):

  1. var http = require(‘http‘);
  2. var wait = function (mils) {
  3.     var now = new Date;
  4.     while (new Date - now <= mils);
  5. };
  6. function compute() {
  7.     // performs complicated calculations continuously
  8.     console.log(‘start computing‘);
  9.     wait(1000);
  10.     console.log(‘working for 1s, nexttick‘);
  11.     process.nextTick(compute);
  12. }
  13. http.createServer(function (req, res) {
  14.     console.log(‘new request‘);
  15.     res.writeHead(200, {‘Content-Type‘: ‘text/plain‘});
  16.     res.end(‘Hello World‘);
  17. }).listen(5000, ‘127.0.0.1‘);
  18. compute();

1、其中compute是一個密集計算的函數,我們把它變為可遞迴的,每一步需要1秒(使用wait來代替密集運行)。執行完一次後,通過process.nextTick把下一次的執行放在隊列的尾部,轉而去處理已經處於等待中的用戶端請求。這樣就可以同時兼顧兩種任務,讓它們都有機會執行。

關於node.js中處理計算密集型,可以參考以下幾種方法:

  • c/c++的addon來實現,在需要進行cpu密集型計算的地方,把js代碼改寫成c/c++代碼;對於不熟悉C++代碼,成本較高
  • 使用cluster建立多進程處理,但編碼複雜度比較高;
  • 讓node支援多執行緒模式的模組:threads_a_gogogithub地址:https://github.com/xk/node-threads-a-gogo(比較好用一些,參考介紹)

 

2、另外:非同步模型的關係,導致某些代碼的執行可能先於它們所需要的條件完成之前,所以將這些需要先置條件的代碼放入到一個回呼函數中,然後放入到下一個事件迴圈的頂層。那麼這些代碼就不會被立刻執行了,而是在下一輪事件啟動之前等待,啟動後在進行執行。

 

範例:

 

var MyConstructor = function() {  ...  process.nextTick(function() {    self._continue();  });}; MyConstructor.prototype.__proto__ = EventEmitter.prototype; MyConstructor.prototype._continue = function() {  // without the process.nextTick  // these events would be emitted immediately  // with no listeners. they would be lost.  this.emit(‘data‘, ‘hello‘);  this.emit(‘data‘, ‘world‘);  this.emit(‘end‘);}; function(req, res, next) {  var c = new MyConstructor(...);  c.on(‘data‘, function(data) {    console.log(data);  });  c.on(‘end‘, next);}

 

Node.js的process.nextTick(callback)理解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.