Node.js開發入門—使用http訪問外部世界
Node.js的http模組,不但可以構建伺服器,也可以作為客戶端類庫來訪問別的伺服器。關鍵就在兩個方法:
- http.request(options[,callback])
- http.get(path[,callback])
除了http,還會用到FileSystem模組和Stream中的stream.Readable和stream.Writable。
先來大概介紹一下相關API吧。
API解釋
http.request()方法接受一個options引數,這個引數可以是物件,用來指明你要訪問的網路資源相關的選項,比如hostname、path、port、method等。下面是一個簡單的選項,用來下載“
var options = {
hostname: 'images.huxiu.com',
port: 80,
method: 'GET',
path: '/article/cover/201509/14/074513891816.jpg',
keepAlive: false
};
http.request()方法返回一個http.ClientRequest例項,呼叫http.request()後,必須在調之後的某個地方呼叫一次req.end,類似下面:
var req = http.request(options, function(res){ console.log(res.statusCode); }); ... req.end();
否則,請求不會發出去哦,你的程式會“呆”在哪裡,茫然不知所措。
而使用http.get()則不用呼叫req.end(),因為http.get()自動幫我們做了。
我們看到http.request()和http.get()都有一個回撥方法,這個回撥方法的引數res是http.IncomingMessage的例項,一個Readable Stream,我們可以通過它來獲取服務端返回的狀態和資料。
實際上我們也可以不提供回撥給http.request()和http.get(),而是通過監聽ClientRequest的response事件來處理服務端反饋。如你所料,response事件需要的回撥和http.request()及http.get()完全一樣。程式碼類似這樣:
var req = http.request(options);
...
req.end();
req.on('response', function(res){
...
});
下載圖片的小示例
示例比較簡單,下載一個圖片並寫入檔案,完成後退出。程式碼如下:
var http = require('http');
var fs = require('fs');
// req is an instance of http.ClientRequest
var req = http.get('http://images.huxiu.com/article/cover/201509/14/074513891816.jpg');
/*
var options = {
hostname: 'images.huxiu.com',
port: 80,
method: 'GET',
path: '/article/cover/201509/14/074513891816.jpg',
keepAlive: false
};
var req = http.request(options, function(res){
console.log(res.statusCode);
});
//req.end() must be called while http.request() is use to issue a request
req.end();
*/
req.on('error', function(e){
console.log(e);
});
var savedStream = null;
var savedFd = 0;
function endSaved(){
if(savedStream != null){
savedStream.end();
}
}
//res is an instance of http.incomingMessage
req.on('response', function(res){
console.log('statusCode - ', res.statusCode);
console.log('contentLength - ', res.headers['content-length']);
if(res.statusCode == 200){
savedFd = fs.openSync('test.jpg', 'w');
if(savedFd > -1){
savedStream = fs.createWriteStream('test.jpg', {fd: savedFd});
console.log('write stream created.');
savedStream.on('finish', function(){
console.log('data saved finished.');
process.exit(0);
});
}
}else{
console.log('error occured.');
process.exit(1);
}
res.on('data', function(chunk){
//console.log('got data - ', chunk);
if(savedStream != null){
if(savedStream.write(chunk)){
console.log('data write directly.');
}
}
});
res.on('close', function(){
console.log('res closed, end save now.');
endSaved();
});
res.on('end', function(){
console.log('res end, end save now.');
endSaved();
});
res.on('error', function(e){
console.log('res err, end save now.');
endSaved();
});
});
我使用http.get()方法來下載圖片。也測試了http.request(),註釋起來的程式碼就是,開啟它,遮蔽http.get()那行程式碼就可以了。
當檔案下載完成時,res(http.IncomingMessage)會發射一個名為“end”的事件,我監聽它來關閉儲存的檔案。
注意我監聽req(http.ClientRequest)的response事件來處理服務端的反饋。開啟檔案時我使用了fs.openSync(),採用同步方式,這樣程式設計更簡單一些。fs.openSync()返回一個檔案描述符(fd),我把它傳遞給fs.createWriteStream來建立一個fs.WriteStream例項,然後使用它來寫檔案。
其它文章: