首頁  >  文章  >  web前端  >  我的Node.js學習之路(三)--node.js作用、回呼、同步與非同步程式碼 以及事件循環_node.js

我的Node.js學習之路(三)--node.js作用、回呼、同步與非同步程式碼 以及事件循環_node.js

WBOY
WBOY原創
2016-05-16 16:42:352077瀏覽

一,node.js的作用,

I/O的意義,(I/O是輸入/輸出的簡寫,如:鍵盤敲入文本,輸入,螢幕上看到文本顯示輸出。滑鼠移動,在螢幕上看到滑鼠的移動。的輸入,和看到的輸出。  
node.js想解決的問題,(處理輸入,輸入,高並發。如在線遊戲中可能會有上百萬個遊戲者,則有上百萬的輸入等等)(node.js適合的範疇:當應用程式需要在網路上傳送和接收資料時Node.js最適合。  
並發的意義,(並發這個術語描述的是事情會在同時發生並可能相互交互。Node的事件化的I/O模型讓我們無需擔心互鎖和並發這兩個在多線程異步I/O中常見的問題)
 
示範網路I/O

Js代碼 

var http = require('http'), 
  urls = ['www.baidu.com','www.10jqka.com.cn','www.duokan.com']; 
function fetchPage(url){ 
  var start = new Date(); 
  http.get({host:url},function(res){ 
    console.log("Got response from:" + url); 
    console.log("Request took:",new Date() - start, "ms"); 
  }); 
} 
for(var i=0; i<urls.length; i++){ 
  fetchPage(urls[i]); 
} 
命名為,node.js
我們在終端機裡面運行node node.js

輸出:

我們要求node.js存取三個url並報告收到回應的情況以及所耗費的時間。

我們可以看到兩次輸出的時間是不一樣的。受各種影響,解析DNS請求的時間,伺服器繁忙程式等等。

 
為什麼javascript是一個事件驅動的語言
javascript圍繞著最初與文檔物件模型(DOM)相關的事件架構。開發人員可以在事件發生時做事情。這些事件有使用者點擊一個元素,頁面完成載入等。使用事件,開發人員可以編寫事件的監聽器,當事件發生時被觸發。
 
二,回調(Callback)
1,什麼是回調
2,剖析回調
 
回調指的是將一個函數作為參數傳遞給另一個函數,並且通常在第一個函數完成後被呼叫。
 
例:如jquery中的hide()方法,
Js代碼 

1,$("p").hide('slow'); 
2,$("p").hide('slow',function(){alert("The paragraph is now hidden")}); 
回調是可選的,
1就不需要回呼

2,是有回調的,當段落隱藏完成後它就會被調用,顯示一個alert提示。
 
為了可以看到帶與不帶回調的代碼之間的區別
Js代碼 

$("p").hide('slow'); 
alert("The paragraph is now hidden");//1 
 
$("p").hide('slow',function(){alert("The paragraph is now hidden")});//2 
1,是沒有回調,,執行順序是一樣但是,我們可以看到p段落還沒有隱藏完全,alert就出來
2,是有回調的,執行則是hide完成後在alert

 
 剖析回調
Js代碼 

function haveBreakfast(food,drink,callback){ 
  console.log('Having barakfast of' + food + ', '+ drink); 
  if(callback && typeof(callback) === "function"){ 
    callback(); 
  } 
} 
 
haveBreakfast('foast','coffee',function(){ 
  console.log('Finished breakfast. Time to go to work!'); 
}); 
 
輸出:


Having barakfast of foast,coffee
Finished breakfast. Time to go to work!
這裡是建立了一個函數,有三個參數,第三個參數是callback,這個參數必須是個函數。
haveBreakfast函式將所吃的東西記錄到控制台中然後呼叫作為參數傳遞給它的回呼函數。

 
Node.js如何使用回呼

node.js中使用filesystem模組從磁碟上讀入檔案內容的範例

 

Js代碼 

var fs = require('fs'); 
 
fs.readFile('somefile.txt','utf8',function(err,data){ 
  if(err) throw err; 
  console.log(data); 
});
結果是:somefile.txt裡面的內容。
1,fs(filesystem)模組被請求,以便在腳本中使用

2,講檔案系統上的檔案路徑作為第一個參數提供給fs.readFile方法
3,第二個參數是utf8,表示檔案的編碼
4,將回呼函數作為第三個參數提供給fs.readFile方法
5,回呼函數的第一個參數是err,用來保存在讀取檔案時傳回的錯誤
6,回呼函數的第二參數是打他,使用者保存讀取檔案所回傳的資料。
7,一旦檔案被讀取,回呼就會被呼叫
8,如果err為真,那麼就會拋出錯誤
9,如果err為假,那麼來自文件的資料就可以使用
10,在本例中,資料會記錄到控制台上。
 
再一個,http模組,http模組使得開發人員可以創建http客戶端和伺服器。

Js代碼 

var http = require('http'); 
 
http.get({host:'shapeshed.com'},function(res){ 
  console.log("Got response:" + res.statusCode); 
}).on('error',function(e){ 
  console.log("Got error:" + e.message); 
 
}); 
 結果:Got response:200
1,請求http模組,以便在腳本中使用

2,給http.get()方法提供兩個參數
3,第一個參數是選項物件。在本範例中,要求取得shapeshed.com的主頁
4,第二個參數是以響應為參數的回呼函數
5,當遠端伺服器傳回對應時,會觸發回調函數。
6,在回呼函數內記錄回應狀態碼,如果有錯誤的話可以記錄下來。
  
 接下來,我們來看看有4個不同的I/O操作都在發生,他們都使用回呼

Js代碼 

 我们能知道哪个操作先返回吗?
猜测就是从磁盘上读取的两个文件先返回,因为无需进入网络,但是我们很难说哪个文件先返回,因为我们不知道文件的大小。对于两个主页的获取,脚本要进入网络,而响应时间则依赖于许多难以预测的事情,Node.js进程在还有已经注册的回调尚未触发之前将不会退出。回调首先解决不可预测性的方法,他也是处理并发(或者说一次做超过一件事情)的高效方法。
下面是我执行的结果


  
 同步和异步代码 

先看代码,同步(或者阻塞)代码

Js代码 

function sleep(milliseconds){ 
  var start = new Date().getTime(); 
  while((new Date().getTime() -start) < milliseconds){ 
 
  } 
} 
function fetchPage(){ 
  console.log('fetching page'); 
  sleep(2000); 
  console.log('data returned from requesting page'); 
} 
function fetchApi(){ 
  console.log('fetching api'); 
  sleep(2000); 
  console.log('data returned from the api'); 
} 
fetchPage(); 
fetchApi(); 

 
当脚本运行时,fetchPage()函数会被调用,直到它返回之前,脚本的运行是被阻塞的,在fetchPage()函数返回之前,程序是不能移到fetchApi()函数中的。这称为阻塞操作。
Node.js几乎从不使用这种编码风格,而是异步地调用回调。
看下下面编码,,

Js代码 

var http = require('http'); 
 
function fetchPage(){ 
  console.log('fetching page'); 
  http.get({host:'www.baidu.com',path:'/&#63;delay=2000'}, 
    function(res){ 
      console.log('data returned from requesting page'); 
    }).on('error',function(e){ 
      console.log("There was an error" + e); 
    }); 
} 
function fetchApi(){ 
  console.log('fetching api'); 
  http.get({host:'www.baidu.com',path:'/&#63;delay=2000'}, 
    function(res){ 
      console.log('data returned from requesting api'); 
    }).on('error',function(e){ 
      console.log("There was an error" + e); 
    }); 
} 
fetchPage(); 
fetchApi(); 

 允许这段代码的时候,就不再等待fetchPage()函数返回了,fetchApi()函数随之立刻被调用。代码通过使用回调,是非阻塞的了。一旦调用了,两个函数都会侦听远程服务器的返回,并以此触发回调函数。
注意这些函数的返回顺序是无法保证的,而是和网络有关。
 
事件循环

Node.js使用javascript的事件循环来支持它所推崇的异步编程风格。基本上,事件循环使得系统可以将回调函数先保存起来,而后当事件在将来发生时再运行。这可以是数据库返回数据,也可以是HTTP请求返回数据。因为回调函数的执行被推迟到事件反生之后,于是就无需停止执行,控制流可以返回到Node运行时的环境,从而让其他事情发生。

Node.js经常被当作是一个网络编程框架,因为它的设计旨在处理网络中数据流的不确定性。促成这样的设计的是事件循环和对回调的使用,他们似的程序员可以编写对网络或I/O事件进行响应的异步代码。

需要遵循的规则有:函数必须快速返回,函数不得阻塞,长时间运行的操作必须移到另一个进程中。
Node.js所不适合的地方包括处理大量数据或者长时间运行计算等。Node.js旨在网络中推送数据并瞬间完成。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn