nodeJS的回撥程式設計 體驗

mageqi發表於2014-08-07
       在nodejs程式碼中,非同步程式設計的直接體現就是回撥。非同步程式設計依託於回撥來實現,但不能說使用了回撥後程式就非同步化了。
下面只能說呼叫了IO 非同步,然後用回撥進行了資料處理。
  
1 . 讀取http 是非同步等待資料流 ,並在回撥函式中進行處理資料

http.get('', function (response) {});

當客戶端傳送請求並接收到完整的服務端響應頭時,就會呼叫回撥函式。在回撥函式中,除了可以使用response物件訪問響應頭資料外,還能把response物件當作一個只讀資料流來訪問響應體資料
在下面函式里
1.1 在http.get 中我們傳入回撥函式 function (response) 進行處理 response
1.2 然後在回撥函式 function (response) 裡 又呼叫了 response.on事件詳見機制 ,在事件 傳入回撥函式
由於在請求的響應資料流是json 格式,要想透過JSON.parse 分析資料,就需要等待資料全部獲取,如果只是部分資料 ,則可能因為資料不全個出錯。 因此在data 實際中 需要將資料合併起來 body.push(chunk); 。然後
在end 資料中對資料進行分心,並獲取需要的資料。
1.3 而針對獲取的資料 需要如何處理,也可以等待回撥函式進行處理,所以在獲取資料完畢後呼叫 callback(geoXY);
function GetXYjson(addrstr, callback)
{
try
{
http.get(''+addrstr+'&resType=json&enc=utf-8&a_k=f519b1aee05755b300c69f742198d6749124bfbaf76b2ea6b45eff3bc8e4399188888×××××d',
function (response) {
var body = [];
var geoXY={};
console.log("Got response: " + response.statusCode);
//console.log(response.headers);
response.on('data', function (chunk) {
body.push(chunk);
//console.log(chunk.toString('utf8'));
});
response.on('end', function () {
console.log( 'jieguo num: %d',body.length);
if (body.length>1)
{
body = Buffer.concat(body);
//console.log(body.toString());
};
try
{
var jsonData = JSON.parse(body);

//console.log(jsonData["list"]);
console.log(jsonData["list"].length);
if (jsonData["list"].length>0)
{
geoXY["address"]=addrstr;
geoXY["name"]=jsonData["list"][0]["name"];
console.log(jsonData["list"][0]["x"]);
geoXY["x"]=jsonData["list"][0]["x"];
console.log(jsonData["list"][0]["y"]);
geoXY["y"]=jsonData["list"][0]["y"];
console.log(' find Geo for num address:%s',addrstr);

}else
{

geoXY["address"]=addrstr;
geoXY["name"]='';
geoXY["x"]=0;
geoXY["y"]=0;
console.log('can not find Geo for num address:%s',addrstr);
}


}
catch(err)
{
// throw err;
geoXY["address"]=addrstr;
geoXY["name"]='';
geoXY["x"]=0;
geoXY["y"]=0;
console.log('Error: %s',err.message);

};
callback(geoXY);
});

});
}
catch(err)
{
console.log('Error: %s',err.message);
throw err;
};

}
2 . 處理多個http請求的響應資料值
2.1 從檔案中讀取請求值,透過data 事件 進行非同步處理 ,傳入回撥函式,對請求值進行http 請求
2.2 呼叫上面單個Http請求 GetXYjson,並傳入該函式的回電函式,在回電函式中逐個將獲取的響應題的值
push 到一個物件,並在最後一個請求回撥返回後,進行處理結果物件。如何處理,透過呼叫回掉函式
callback(geosObj);
function GetXYSFromFileAsyc(src,callback)
{
var rOption ={ flags: 'r',
encoding: 'utf8',
fd: null,
mode: 0666,
autoClose: true
};

var frs = fs.createReadStream(src,rOption);
var geosObj=[];
frs.on('data', function(chunk){
console.log('got %d bytes of data', chunk.length);
var strLines=chunk.split('\n');
for(var i=0,size=strLines.length;i console.log('data%d:%s',i,strLines[i]);
if (strLines[i].length>0)
{
try
{
// 透過函式返回值 肯定是有問題的 因為GetXYjson 呼叫非同步處理資料
// var oneGeo=GetXYjson(strLines[i]);
//geosObj.push(oneGeo);
GetXYjson(strLines[i], function(oneGeo)
{
geosObj.push(oneGeo);
console.log('data %s: push XY ',JSON.stringify(oneGeo));
console.log('geosObj len %D: ',geosObj.length);
if ( geosObj.length==size )
{
console.log('push end');
callback(geosObj);
} ;
});
}
catch(err)
{
console.log('data%d: err:%s',i,err.message);
continue;

}
};
}
});
frs.on('end',function(){
console.log('readStream end');
});
console.log('read end');
// return geosObj;
}
3. 等待所有響應獲取分析完畢後 ,進行統一寫入檔案處理
呼叫GetXYSFromFileAsyc函式進行檔案處理,並傳入回撥函式,對響應值進行寫入操作。
function writeGeoXYtoFile(src,dst)
{
var wOption = {
flags: 'a',
encoding: 'utf8',
mode: 0666 ,
autoClose: true
};
var fws = fs.createWriteStream(dst,wOption);

GetXYSFromFileAsyc(src, function(geosObj)
{
fws.write(JSON.stringify(geosObj),'utf8');
// fws.write(Buffer.concat(geosObj),'utf8');
console.log('write end ');
});

// 有問題 非同步 和同步 有問題 向下程式碼 有問題,就是用同步的思想,處理非同步函式呼叫
/*
var geosObj=[];
geosObj=GetXYSFromFile(src);
console.log('lengh',geosObj.length);
if (geosObj.length>0)
{
fws.write(Buffer.concat(geosObj),'utf8');

}
console.log('write end ');
*/
//console.log('get geo %d',data.length);

}

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/523892/viewspace-1247328/,如需轉載,請註明出處,否則將追究法律責任。

相關文章