Node.js學習筆記

/**

 *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);

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章