/**
*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=byvoid@byvoid.com
*结果如下:Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?name=byvoid&email=byvoid@byvoid.com',
query:{ name: 'byvoid', email: 'byvoid@byvoid.com' },
pathname: '/user',
path:'/user?name=byvoid&email=byvoid@byvoid.com',
href:'/user?name=byvoid&email=byvoid@byvoid.com' }
*/
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);
}