Nodejs开发指南-笔记
第三章 异步式I/O与事件编程
3.1 npm install -g supervisor
supervisor app.js 当后台修改代码后,服务器自动重启,生效修改的代码,不用手动停止/启动
3.2 单线程异步I/O
减少了多线程的开销,对于操作系统,创建线程的开销很大,需分配内存、列入调度。同时线程切换时
需要内存换页,CPU的缓存被清空,切换回来时,需要重新从内存中读取信息,破坏了数据的局部性。
异步读取文件:
var fs = require('fs') fs.readFile('test.txt','utf-8',function(err,data){
if(err){
console.log(err);
}
else console.log(data);
}) console.log('end'); 输出:
end;
content of the test.txt
3.3模块和包
3.3.1、模块
什么是模块:
一个文件就是一个模块。
创建模块:
exports和require实现
举例说明
//module.js
var name;
exports.setName = function(thyname){
name = thyname;
} exports.getName = function(){
console.log(name);
} //getnodule.js
var module = require('./module') module.setName('xxx')
module.getName(); 对于对象的封装:
//hello.js
function Hello(){
var name;
this.setName = function(thyname){
name = thyname;
};
this.sayHello = function(){
console.log("Hello "+name);
}
} module.exports = Hello; //gethello.js
var Hello = require('./hello') var hello = new Hello();
hello.setName("xxx");
hello.sayHello();
3.3.2、包
将一个文件夹封装成一个模块,即所谓的包
(1)作为文件夹的模板
1、建立一个somepackage文件夹
2、在somepackage下建立index.js文件 (必须是index.js)
3、文件中写入
exports.hello=function(){
console.log('Hello World');
};
在somepackage文件夹外建立一个getpackage.js文件
写入
var somepackage=require('./somepackage');
somepackage.hello();
3.2.2 package.json
在主目录下创建package.json,写入:
{
"main":"./lib/interface.js"
}
在主目录中建立lib子文件夹,并在其中创建interface.js文件,在文件中写入 exports.hello=function(){
console.log('Hello Node.js');
};
运行上面的getpackage.js得到相同的结果。
Node.js在调用某个包时,会首先检查包中package.json中的main字段,将其作为包的接口模块,如果main不存在,会尝试寻找index.js或者index.node作为包的接口
3.4nodejs的包管理器npm
npm install [包名]
npm install -g [包名]//全局目录安装
创建的全局模式的包,不能直接require使用,需要创建全局链接
npm link [包名]
./node_moudles/[包名] -> /usrt/local/lib/node_moudles/express
3.5npm包的发布
1、npm init 填写好package.json信息
2、npm adduser 按照提示填写账号信息,用于以后维护包
3、npm publish 发布包
打开浏览器 http://npmjs.org/可以查找到,而且在世界商任意一台主机上,都可以用npm install [包名]来安装你发布的包
3.6调试
3.6.1命令行调试
在设置断点的代码处添加debugger
node debug app.js
进入调试界面,help查看调试命令
3.6.2远程调试
//在一个终端里(不加port,默认是5858)
node --debug-brk[=port] app.js
或 node --debug[=port] app.js
//在另一个终端中
node debug 127.0.0.1:5858或 node debug 127.0.0.1:[port]
3.6.3node-inspector调试
npm install -g node-inspector
//运行脚本
node --debug-brk=5858 app.js
//启动node-inspector
$ node-inspector
//打开浏览器
http://127.0.0.1:8080/debug?port=5858
第四章nodejs核心模块
4.1全局对象
永远使用var定义变量,避免引入全局变量,因为你全局变量会污染明明空间。
4.1.1 process.argv命令行参数数组
第一个参数是node 第二个参数是脚本文件名,第三个参数是运行参数
4.1.2 process.nextTick(callback)
为事件循环设置一项任务,将复杂的任务,拆分成一个个较小的事件
举例说明:
function doSomething(callback){
compile()
callback()
} doSomething(function onEnd){
compute()
}
改进后
function doSomething(callback){
compile()
process.nextTick(callback)
} doSomething(function onEnd){
compute()
}
改进后的程序会把上面耗时的操作拆分位两个事件,减少每个事件的执行时间,提高时间响应效率。
4.2常用工具util
4.2.1 util.inspect将人已对象转换成字符串。
util.inspect(object.[showHidden],[depth],[color])
showHidden可选参数,如果是true,输出更过隐藏信息
depth可选参数,最大递归层数,默认2,指定为null表示不想递归层数,完整遍历。
color可选参数,true表示输出格式以ANSI颜色编码,终端显示更漂亮。
4.3事件驱动events(最重要的模块)
4.3.1事件发射器
events.EventEmitter 时间发射和时间监听
var events = require('events')
var emitter = new events.EventEmitter() emitter.on('someEvent',function(arg1,arg2){
console.log('listen ',arg1,arg2)
}) emitter.emit('someEvent','byvoid',1991)
输出
listen byvoid 1991
4.4文件系统fs
4.4.1 fs.readFile()异步读取文件
fs.readFile('filename','utf-8',function(err,data){
if(err){
console.log(err)
}
else{
console.log(data)
}
})
4.4.2 fs.readFileSync(filename,[encoding])同步读取文件
4.4.3 fs.open(path,flags,[mode],[callback(err,fd)])
path:文件路径, flags:r,r+,w,w+,a,a+ 两个必选参数
mode:用于创建文件时给文件的指定权限,默认是0666
4.4.4 fs的其他常用函数:
1)读取文件
异步:fs.readFile(filename,[encoding],[callback(err,data)])
同步:fs.readFileSync(filename,[encoding])
2)写入文件(清空原有的)
异步:fs.writeFile(filename,data,[encoding],[callback(err)])
同步:fs.writeFileSync(filename,data,[encoding])
3)追加写入文件
异步:fs.appendFile(filename,data,[encoding],[callback(err)])
同步:fs.appendFileSync(filename,data,[encoding])
4)删除文件
异步fs.unlink(path,[callbacl(err)])
同步:fs.unlinkSync(path)
5)创建目录
异步:fs.mkdir(path,[mode],[callback(err)])
同步:fs.mkdirSync(path,[mode])
6)删除目录
异步:fs.rmdir(path,[callback(err)])
同步:fs.rmdirSync(path)
7)读取目录(读取目录下的所有文件,输出一个数组)
异步:fs.readdir(path,[callback(err)])
同步:fs.readdirSync(path)
8)获取文件真实路径
异步:fs.realpath(filename,[callback(err,files)])
同步:fs.realpathSync(filename)
9)更名
异步:fs.rename(path1,path2,[callback(err)])
同步:fs.renameSync(path1,path2)
10)更改权限
异步:fs.chmod(path,mode,[callback(err)])
同步:fs.chmodSync(path,mode)
11)更改所有权
异步:fs.chown(path,uid,gid,[callback(err)])//uid和gid为整形,linux下运行id命令可以查询
同步:fs.chownSync(path,uid,gid)
第六章 Nodejs进阶话题
6.1 加载缓存
nodejs不会重复加载,这是因为nodejs通过文件名缓存所有加载过的文件模块,所以以后再放问到时,就不会重复加载了。require后只需加载一次
6.2 Nodejs应用部署
6.2.1 不支持故障恢复
当程序发生错误时,后台直接垮掉
6.2.2 没有日志输出
解决方法:Express支持另种运行模式:开发模式和产品模式。前者用于调试,后者用于部署。
只需设置NODE_ENV变量即可,NODE_ENV = production实现产品模式,node app.js可以看到
Express server listening on port 3000 in production
在app.js的最上方添加一下代码,实现日志打印
var fs = require('fs'); var accessLogfile = fs.createWriteStream('access.log',{flags:'a'});
var errorLogfile = fs.createWriteStream('error.log',{flags:'a'});
app.use(express.logger({stream: accessLogfile}))
//对于错误日志,需要单独实现错误响应 app.config('production',function(){
app.error(function(err,req,res,next){
var meta = '['+ new Date() +']' + req.url+'\n';
errorLogfile.write(meta+err.stack+'\n');
next();
})
})
6.2.3 无法利用多核提高性能(单线程)
解决方法:cluster模块。cluster的功能是生成与当前进程相同的子进程,并允许子进程和父进程之间共享端口。
调用cluster模块,将主进程生成若干工作进程。
6.2.4 独占端口
解决方法:利用ngix,通过反向代理实现nodejs虚拟主机
下面举例配置文件
server {
listen 80;
server_name mysite.com;
location /{
proxy_pass http://localhost:3000;
}
}
该配置文件的功能是,监听访问mysite.com 80端口的请求,并将多有的请求转发给localhost:3000
6.2.5 需要手动启动(重启服务器的化)
解决方法:编写开机脚本
6.3 nodejs不适合做什么
6.3.1 不适合计算密集型程序
6.3.2 不适合单用户多任务应用。
node适合解决大量并发请求,单用户不存在并发请求。
6.3.3 不适合逻辑十分复杂的事物
node更善于处理逻辑简单但访问频繁的任务。
附录A JavaScript的高级特性
A-1、作用域
js的作用域是通过函数来定义的。变量的搜索由函数内向函数外扩展
var scop = "global" var f = function(){
console.log(scop);//输出undefined
scop = "f";
}
注:js访问未定义或着定义了但未初始化的变量,都是undefined
A-2、对象
js只有对象,对象就是对象,不是类的实例
js中的对象不是基于类实现的,而是基于原型实现的。
1、var foo = {} //即为对象
foo.prop_1 = 'bar'
2、使用对象初始化器创建对象
var foo = {
prop1:'bar',
prop2:function(){
}
}
3、使用构造函数创建对象
function User(name, uri){
this.name = name;
this.uri = uri;
this.display = function(){
return this.name;
}
}
var someuser = new User('name','http://baidu.com')
4、上下文对象(call)
call可以实现继承。
user = {
name:"xxxx",
uri:'baudu.com',
display: function(words){
console.log(this.name+" "+words)
}
} var foo = {
name:'foobar'
}
user.display.call(foo,'hello')
输出: foobar hello
A-3、原型
利用原型来初始化对象
function Foo(){}
Foo.prototype.name = "user"
Foo..prototype.getName = function() {
return this.name
};
var foo = new Foo()
foo.getName()//输出user
举例说明构造函数内创建属性和原型定义成员函数的区别
function Foo(){
this.prop = "prop";
this.getProp = function(){
return this.prop
}
}
Foo.prototype.name = "user"
Foo..prototype.getName = function() {
return this.name
}; var foo1 = new Foo()
var foo2 = new Foo()
console.log(foo1.getProp ==foo2.getProp)//false
console.log(foo1.getName ==foo2.getName)//true
构造函数内定义的任何属性,包括函数在内都被重复构建,同一个构造函数产生的两个对象不共享实例。
所以尽量用原型定义成员函数,减少开销。
尽量在构造函数内定义一般成员,尤其是数组或对象,因为原型中定义的成员是多个实例共享的。
B、Nodejs编程规范
1、两个空格做缩进
2、分号做换行符
3、var定义变量 绝对不能使用赋值隐式定义的变量(全局变量,空间污染),确保每个语句定义一个变量,(不能定义多个变量,之间用','分割)
4、变量名和属性名(驼峰式命名空间)
5、对于函数定义,() {}之间要有一个空格
6、同意使用单引号
7、等号尽量使用===
8、命名函数
回调函数和构造函数,尽量给函数命名。
对于回调函数,Nodejs和第三方模块约定第一个参数是err
9、对象定义
所有成员函数,尽量用原型进行定义,属性在构造函数内定义,然后对构造函数用new进行对象的创建
Nodejs开发指南-笔记的更多相关文章
- nodejs开发指南读后感
nodejs开发指南读后感 阅读目录 使用nodejs创建http服务器; supervisor的使用及nodejs常见的调式代码命令了解; 了解Node核心模块; ejs模板引擎 Express 理 ...
- 《nodejs开发指南》微博实例express4.x版
之前一直执着于前端开发,最近几天,开始学起了nodejs.作为一名前端开发者,见到这样一门用javascript写的后台自然是很激动的.但是,后台毕竟不同于前端,在学习的过程中,还是会遇到不少问题. ...
- 《NodeJS开发指南》第五章微博实例开发总结
所有文章搬运自我的个人主页:sheilasun.me <NodeJS开发指南>这本书用来NodeJS入门真是太好了,而且书的附录部分还讲到了闭包.this等JavaScript常用特性.第 ...
- 《NodeJs开发指南》第五章微博开发实例的中文乱码问题
在<NodeJs开发指南>第五章,按照书中的要求写好微博实例后,运行代码,发现中文显示出现乱码,原因是:views文件夹下的ejs文件的编码格式不是utf-8. 解决方法:以记事本方式打开 ...
- Django Web开发指南笔记
Django Web开发指南笔记 语句VS表达式 python代码由表达式和语句组成,由解释器负责执行. 主要区别:表达式是一个值,它的结果一定是一个python对象:如:12,1+2,int('12 ...
- 读《nodejs开发指南》记录
最近看了一下<nodejs开发指南>发现nodejs在某些特定的领域由他自己的长处,适合密集计算但是业务逻辑比较简单的场景,如果做网站还是选择php吧,呵呵,这本书我除了第5章<用n ...
- 使用express4.x版、Jade模板以及mysql重写《nodejs开发指南》微博实例
最近阅读<nodejs开发指南>一书,书是不错的,然而其微博代码示例用的是express3.x,用些过时了,运行代码出现不少bug(我电脑安的是express4.x),于是用express ...
- [Lua游戏AI开发指南] 笔记零 - 框架搭建
一.图书详情 <Lua游戏AI开发指南>,原作名: Learning Game AI Programming with Lua. 豆瓣:https://book.douban.com/su ...
- nodejs 开发指南 书中小项目 代码
最近 在学习node.js 先看了下语法 ,然后就看这个开发指南感觉书还是很有用,但是代码太旧了,网上也没有最新的,所以就自己查着前人的痕迹和自己修改,现在可以跑了. https://github.c ...
随机推荐
- Android里的多线程知识点
1.Thread类与Runnable接口 子类继承Thread类实现跑自己逻辑的run方法,在调用Thread类的start方法后,会自动调用run方法,该对象只可以调用一次start方法,即Thre ...
- kettle的jdk1.7环境变量配置
1).到官网下载需要安装的kettle版本,目前最新版本4.2,官网地址:http://kettle.pentaho.org,我们是使用的版本是kettle3.2 2).本地安装jdk 1.4或以上版 ...
- 《OD大数据实战》mac下安装nginx+php
一.mac安装nginx + php + php-fpm 或apache + php 1. Mac 下 Nginx.MySQL.PHP-FPM 的安装配置 2. Mac下安装LNMP(Nginx+P ...
- hdu4430Yukari's Birthday(二分)
4430 去年长春最简单一题 二分啊 错了好多遍 有个大坑 是个圆心处的1 可选可不选 #include <iostream> #include<cstdio> #incl ...
- Servlet的延迟加载和预加载
我们什么时候使用了延迟加载呢? 先从hibernate引入这个概念吧. hibernate使用lazy属性设置延迟加载,load方法会使用延迟加载. 举个例子: 一个学生有多部手机,如果使用了延迟加载 ...
- #define | enum(enumerator)
/**************************************************************************** * #define | enum(enume ...
- QCon 2015 阅读笔记 - 移动开发最佳实践
所有ppt下载地址:http://pan.baidu.com/s/1mg9o4TM 下面是移动开发实践部分的阅读笔记. 移动开发网络性能优化实践 - 陈浩然 (携程) 携程是非常标准的移动App架构, ...
- 20160130.CCPP体系详解(0009天)
程序片段(01):hanoi.c+汉诺塔.c 内容概要:汉诺塔 ///hanoi.c #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> ...
- swun 1397 来电显示
解题思路:这题最关键的是要注意当输入的数据,00123,0000等这些情况, 刚开始用long long, WA了好几发,非常迷茫,后来突然想起特殊数据, 用字符串,则轻松解决问题.顺便多说两句:当你 ...
- java-过滤器-监听器-拦截器
1.过滤器 Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码.做一些业务逻辑判断等.其工作原理是,只要你在web.xml ...