/**
*Created by Monulix on 2018/5/10.
**/
//console.log("Good Bye,World");
//var fs = require('fs');
//fs.readFile('1.txt','utf-8',function(err,data){
// if(err){
// console.error(err);
// }else{
// console.log(data);
// } //異步
//}); //何時事件隊列進入回調函數;
//console.log('end dif');
//
//var data =fs.readFileSync('1.txt','utf-8');
//console.log(data);
//console.log('end syn'); //輸出結果很像同步,難道該API曾被重構爲異步;
//
///**javaScript 中的異步請求;**/
//function callbackfun(err,data){
// if(err){
// console.log(err);
// }else{
// console.log(data);
// }
//}
//var fs1 = require('fs');
//fs1.readFile('1.txt','utf-8',callbackfun);
//console.log('javaScript end.'); //多個異步進行時,事件隊列何時進入?
////node.js所有的異步IO操作都會發出一個事件到事件隊列;
//console.log('\n');
//var Event =require('events').EventEmitter;
//var eve = new Event();
//
//eve.on('some_event',function(){
// console.log('\n10ss後發送使能信號,1slater,a tone');
//});
//setTimeout(function(){
// eve.emit('some_event');
// },3000);
////for(var i = 0;i < 10000;++i){
//// process.stdout.write('a');
//// if((i % 27 == 0)||(i % 98 == 0)){
//// process.stdout.write('\n');
//// }
////}
////Node.js事件循環機制:
// //程序的入口就是事件循環的第一個事件的回調函數(類似於main()),從事件循環開始,到事件循環結束;
///**回調函數執行時,可能會發出I/O請求或直接發射(emit)事件,執行完畢後
// 再返回事件循環,事件循環會檢查事件隊列中有沒有未處理的事件,直到
// 程序結束;
// Node.js沒有顯式的事件循環,類似Ruby的EventMachine::run()的函數在
// Node.js中不存在,由libev庫實現(被EventEmitter封裝)。**/
//
////require();覆蓋
//var http1 = require('http');
////http1.method();
//
//var http2 = require('http'); //無論調用多少次,實際對象只加載一次;
////http2.method();
////http1和http2是引用語義,指向同一個http對象,兩者的輸出是
//// 相同的,因爲後者會覆蓋前者。
//
////module.exports = Hello; instead theexports.Hello = Hello;
////**外部引用該模塊時,接口對象是Hello對象本身,而不是原先的
////exports */
//
////exports本身是普通的控對象,即{},專門用來聲明接口,
////本質上是通過它爲模塊閉包的內部建立了一個有限的訪問接口。
////不可以通過對export直接賦值代替對module.exports賦值。
////exports實際上是一個和module.exports指向同一個對象的變量;
////,但module不會,只能通過指定nodule.exports來改變訪問接口。
//
////"package.json"
//// npm install express 該包與python的pip和Ruby的gem不同;
////npm默認安裝到當前目錄,其他兩個是安裝到全局;
//
////npm i -g可以安裝到全局;
////全局模式安裝的包require不能在上層目錄尋找;但
////通過npm -link的全局鏈接可以打破限制;
//
////如 npm link express
//// ./node_modules/express ->/usr/local/lib/node_modules/express
////鏈接後可當做本地目錄使用
//
////npm link 不支持windows;與管理員權限有關;
////命令行下單步調試;
//
////node debug debug.js
////遠程調試, --debug = 1234,指定調試端口爲1234;
////node debug 127.0.0.1:5858
////connecting... ok
////...
//
////核心模塊
//
////JS中的全局對象是window;Node.js中的全局對象是global;
////所有全局變量(除了global本身)都是global對象的屬性;
////能直接訪問到的對象基本歐式global對象的屬性;
//
//
////process.stdin.resume(); //初始輸入流掛起
////
////process.stdin.on('data',function(data){
//// process.stdout.write('from console read:' +
//// data.toString());
//// if(data == null){
//// process.stdout.write();
//// return
//// }
////});
//
//
////以下代碼報callback不是一個函數;
//process.stdout.write("10010110".toString());
//process.nextTick(cback_func);//存在多個複雜任務時;
//
//function doSomething(args, cback_func){
// sthComplicated(args); //複雜過程;先1
// process.nextTick(cback_func); //立即回調,
// //不用setTimeout(fn,0)代替process.nextTick(callback)
// //效率低下
//}
//function cback_func(){
//
//}
// doSomething(function onEnd(){ //執行onEnd
// compute(); //複雜過程2
// });
//
//function sthComplicated(args){
// console.log("SthComplicated");
//}
//
//function compute(){
// console.log("compute");
//} //複雜過程2
//上述代碼有錯誤,後面再查;
//new pro
//console.trace();
//util工具類;
//js的面向對象特性是基於原型的;
var util = require('util');
function Base() {
this.name = 'base';
this.base = 1991;
this.sayHello = function() {
console.log('Hello ' + this.name);
};
}
Base.prototype.showName = function() {
console.log(this.name);
};
function Sub() {
this.name = 'sub';
}
util.inherits(Sub, Base); //實現對象間原型繼承;
var objBase = new Base();
objBase.showName();
objBase.sayHello();
console.log(objBase);
var objSub = new Sub();
objSub.showName();
//objSub.sayHello(); //類內部不被繼承,原型方法才繼承;與
//基於類的面向對象有差別;
console.log(objSub);
//
var util = require('util');
function per(name){
this.name = name;
this.toString = function(){
return this.name;
};
}
var obj = new per('12');
console.log('\n'+'person::');
console.log(util.inspect(obj));
console.log(util.inspect(obj,true));
//events模塊;是node.js最重要的模塊,沒有之一。
//4.3.1 事件發射器 核心對象:events.EventEmitter;核心是事件發射器與事件監聽器功能的封裝;
console.log("\n事件與監聽器***************");
var events = require('events');
var emitter = new events.EventEmitter();
emitter.on('Event', function(arg1,arg2){
console.log('listener1', arg1, arg2); //emitter爲事件someEvent註冊了事件監聽器1;
var iRls = arg1 + arg2;
console.log(iRls);
});
emitter.once('Event', function(arg1,arg2){
console.log('listener2', arg1, arg2); //emitter爲事件someEvent註冊了事件監聽器2;
var iRls = arg1 * arg2;
console.log(iRls); //once爲單次監聽,觸發後立即解除。
});
emitter.emit('Event',9,1991);
console.log("事件與監聽器******************");
console.log('error事件********************');
/**
*node.js的錯誤處理是通過事件和監聽器機制來實現的;
*@type {exports}
*/
var events = require('events');
var Emitter_GUI = newevents.EventEmitter();
Emitter_GUI.on('error',function(arg1,arg2){
var error_rls = arg1/arg2;
console.log(error_rls);
});
Emitter_GUI.emit('error',10,0);
console.log('error事件(異常處理???)********************\n');
//繼承EventEmitter;
console.log('*************fileread*************');
var fs = require('fs');
fs.readFile('1.txt','utf-8',function(err,data){
if(err){
console.log(err);
}else{
console.log('\n'+data.toString());
}
});
console.log('*************fileread.close*******\n');
console.log('*************文件同步讀寫sync readwrite*******\n');
var fs1 = require('fs');
try{
fs1.readFileSync('0.txt');
}
catch(err){
console.log(err);
}
console.log('*************compelte syncreadwrite*******\n');
console.log('*************fs.open*******\n');
var fs = require('fs');
fs.open('1.txt','r+',function(err, fd){
if(err) {
console.log(err);
return;
}
var buf = new Buffer(8); //緩衝區大小爲八個字節
fs.read(fd, buf, 0, 8, null,
function(err, byteRead, buffer){
if(err){
console.log(err);
return;
}
console.log('byteRead' + byteRead);
console.log(buffer.toString());
})
});
console.log('*************complete,fs.open*******\n');
console.log('*************http server andclient*******\n');
var http = require('http');
http.createServer(function(req,res){
res.writeHead(200, {'Content-Type':'text/html'});
res.write('<h1>ByeBye World</h1>');
res.end('<p>qian zong niu bi</p>');
}).listen(12000);
console.log("http server listening atport 2000:");
console.log(">>>>>>>>>>>httpserverRequwst:>>>>>>>>>");
console.log(">>>>>>>>>>>獲取get 請求內容:>>>>>>>>>");
var http = require('http');
var url = require('url');
var util = require('util');
http.createServer(function(req, res){
res.writeHead(200,{'Content-Type': 'text/plain'});
res.end(util.inspect(url.parse(req.url, true)));
}).listen(12001);
/**
* 在瀏覽器中訪問 http://127.0.0.1:12001/user?name=byvoid&[email protected]
*結果如下:Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?name=byvoid&[email protected]',
query:{ name: 'byvoid', email: '[email protected]' },
pathname: '/user',
path:'/user?name=byvoid&[email protected]',
href:'/user?name=byvoid&[email protected]' }
*/
console.log(">>>>>>>>>>>獲取post 請求內容:>>>>>>>>>");
//httpserverrequestpost.js
var http = require('http');
var querystring = require('querystring');
var util = require('util');
http.createServer(function(req, res) {
var post = '';
req.on('data', function(chunk) {
post += chunk;
});
req.on('end', function() {
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(12002);
//不要在真正的生產應用中使用上面這種簡單的方法來獲取 POST 請
//求,因爲它有嚴重的效率問題和安全問題,這只是一個幫助你理解的示例。
//http.ServerResponse;
console.log(">>>>>>>>>>>httpclient:>>>>>>>>>");
//http.request(options, callback);
//MVC模式:模型 視圖控制器
/**
*
*@type {exports} 服務器向用戶返回信息;
*/
console.log(">>>>>>>>>>>返回請求:>>>>>>>>>");
var http = require('http');
var querystring = require('querystring');
var server =http.createServer(function(req, res) {
varpost = '';
req.on('data', function(chunk) {
post += chunk;
});
req.on('end', function() {
post = querystring.parse(post);
res.write(post.title);
res.write(post.text);
res.end();
});
}).listen(3000);
//*********php方式*********//
//echo $_POST['title'];
//echo $_POST['text'];
console.log(">>>>>>>>>>>Expressframework:>>>>>>>>>");
//安裝express
//$ npm install -g express
//express --help
//supervisor 實現監視代碼修改和自動重啓
//app.js是工程的入口;樣式表style.css;
//路徑匹配
console.log(">>>>>>>>>>>Expressframework cannot run:>>>>>>>>>");
//app.get('/usr/:username', function(req,res){
// res.send('user: ' + req.params.username);
//});
//REST風格的路由規則
//route/index.js是路由文件,用於組織展示的內容;
/**
*GET home page.
*/
exports.index = function(req, res){
res.render('index', {title: 'Express' });
};
/**
*module dependencies
*/
//MongoDB是對象數據庫,JSON格式;
/**
* app.js
*/ //沒有express對象,未添加依賴;
//var express = require('express'),
// routes = require('./routes');
//
//var app = module.exports =express.createServer();
//app.configure();
/**
* route/index.js 路由文件、Ctrl相當於控制器,用於組織展示內容;
* index.ejs是模板文件,即routes/index中調用的模板;
* layout.ejs所有模板繼承自layout.ejs,可看做頁面框架;
*/
/**
* 瀏覽器——>路由控制器——>(模板引擎,靜態文件,對象模型)
* 模塊加載機制
* 異步編程模式下的控制流
* Node.js應用部署
* Node.js的劣勢
*/
//fs,http,net,vm 加載優先級:.js, .json, .node;
//.json是json格式的文本;.node是編譯好的C/C++代碼;
//控制流
//循環陷阱:
var fs = require('fs');
var files = ['1.txt', '2.txt', '3.txt'];
/**
*callback function在循環結束以後才能訪問到外面的值;
* 回調函數在此體現的淋漓盡致;
*/
for(var i = 0; i < files.length; ++i){
fs.readFile(files[i], 'utf-8', function(err, data){
console.log(i + '\t' + files[i] + '\n');
// i 的值3次都爲3;
// file[i]越界報undifined;
// 可見越界一般都報undifined就是未曾定義的對象;
console.log(files[i] + ':' + data + '\n');
});
}
//對以上過程進行更改,使得在合適的時間訪問到相應的i;
var fs = require('fs');
var files = ['1.txt', '2.txt', '3.txt'];
for(var i = 0; i < files.length; ++i){
(function(i){
//利用js函數式編程特性,對回調函數進行閉包操作,
fs.readFile(files[i], 'utf-8', function(err, data){
console.log(i + '\t' + files[i] + '\n');
console.log(files[i] + ':' + data + '\n');
});
})(i);
console.log(i);
}
console.log("<<<<<<<<<forEachcallback function<<<<<<<<<<<<<");
//出於可讀性考慮,使用ForEach來替代以上寫法;
files.forEach(function(file){
fs.readFile(file, 'utf-8', function(err, data) {
console.log(file + ':' + data); //forEach 隱式閉包;
});
});
//控制流解耦模塊;async;提供了async.series、async.parallel、async.waterfall
//等函數,代替函數嵌套使得程序變得清晰易讀且易於維護,但必須遵守其約定的編程風格。
//stramlines和jscex實現了JS到JS的解釋器,使用戶可以用同步編程的
//模式寫代碼,但編譯爲異步的進行執行的中間代碼;
//eventproxy深度封裝事件發射器,採用完全基於事件鬆散耦合的方式來梳理
//控制流(以上都屬於侵入式的手段);
//應用部署:不適合在產品環境中使用; node app.js
//日誌功能:
//Express支持開發模式和產品模式:前者利於調試,後者利於部署。
//node.js適合邏輯簡單但訪問頻繁的任務;不適合邏輯十分複雜的工作;
console.log("<<<<<<<<<<<<<由於環境崩潰,以下代碼未全面測試,或有疏漏,敬請諒解指正<<<<<<<<<<");
console.log("<<<<<<<<<node.js的日誌模塊<<<<<<<<<<");
//使用產品模式運行服務器,只需設置NODE_ENV環境變量。通過NODE_ENV= productionnode app.js命令運行服務器
//可以看到 Express server listening on port 3000 in production mode;
//包含訪問日誌和錯誤日誌功能;{訪問日誌記錄用戶對服務器的請求;含客戶端IP地址,訪問時間,訪問
// 路徑,服務器響應以及客戶端代理字符串。錯誤日誌則記錄程序發生錯誤時的信息}。
//Express提供了一個訪問日誌中間件,只需要指定stream參數爲一個輸出流即可寫入日誌到文件;
//在app.js文件中,加入以下代碼:
var fs = require('fs');
var accessLogfile =fs.createWriteStream('access.log', {flags: 'a'});
var errorLogfile =fs.createWriteStream('error.log', {flags: 'a'});
//app.configure函數第一行加入:app.use(express.logger({stream: accessLogfile}));
//錯誤日誌需要單獨實現錯誤響應:
app.configure('production', function() {
app.error(function(err, reg, res, next) {
var meta = '[' + new Date() + ']' +req.url + '\n';
errorLogfile.write(meta + err.stack + '\n' );
next();
});
});
//通過.app.error註冊錯誤響應函數,
//throw new Error('An error for test purposes.'); //以此來拋出自定義異常;
//cluster模塊。cluster的功能是生成與當前進程相同的子進程,允許父進程和子進程之間共享端口;
//Node.js的另一個模塊child_process也提供類似的進程生成功能,cluster允許跨進程端口複用;
//在外部調用app.js,需要禁止服務器自動啓動。修改app.js,在app.listen(3000);前後加上判斷語句;
if(! module.parent) {
app.listen(3000);
console.log("Expressserver", app.address().port, app.settings.env);
}