模块化开发(三)---通过node.js学习模块化开发
由于改文章有点大,部分代码格式有点问题,编辑之后博客园莫名其妙推出,有问题可以留言沟通。
什么是Node?
它是一个在浏览器之外可以解析和执行javascript代码的运行环 境,或者说是一个运行时平台,理论意义上就是javascript语言 在服务器端的运行环境。
由于Google V8引擎执行JavaScript的速度非常快,node作者把Chrome的v8引擎单独的移植了出来,Node对一些特殊用例进行了优化,提供了替代的API,使得V8在非浏览器环境下运行的更好。
基于这个引擎之 上,构建了一些底层的API,例如:文件操作,网络通信,给上层 的js提供了友好的API来供开发人员使用。
验证Node是否安装成功:打开控制台CMD-->node -v --->输出当前node环境版本,就说明安装成功。
相关网站:
- [官网](https://nodejs.org/en/)
- [中文API文档](http://nodeapi.ucdok.com/)
- [菜鸟教程 - node](http://www.runoob.com/nodejs/nodejs-tutorial.html)
- [node中文社区](http://cnodejs.org/)
- [node入门](http://www.nodebeginner.org/index-zh-cn.html)
- [七天学会NodeJS](https://nqdeng.github.io/7-days-nodejs/)
1、server.js文件:
var http = require('http');http.createServer(function(req,res){res.writeHead(200,{'Content-Type':'text/plain'});res.end('Hello world \n');}).listen(1337,'127.0.0.1');console.log("Server running at http://127.0.0.1:1337/");执行:在控制台,当前文件夹下,node server.js
2、REPL(Read-Eval-Print-Loop)运行环境
进入环境中: 执行 node 命令
在控制台中输入 node 并执行后,如果在新的一行得到一个 > 提示符,就说明已经成功进入node环境中。
退出环境:
ctrl + c 两次 或者 执行 .exit 命令
3、Node天生就是模块化的,一个文件模块中定义的变量、函数、对象等都属于当前模块作用域。
var foo ='bar';
console.log(foo); //输出 bar
console.log(global.foo); //输出 undefined
global.foo=foo;
console.log(global.foo); //输出 bar
通过给 global 全局对象添加属性可以实现变量共享,但是不推荐使用;可以使用 module.exports 或者 exports.属性 将内容暴漏出去供其他文件使用(暴漏出去的是个对象)。
4、JS文件中指定静态路径问题
加载图片等文件时无论在哪个js文件中写,路径都是根据当前页面来写的。
5、node.js特性
事件驱动 (event-driven)非阻塞 I/O 模型 (non-blocking I/O model )轻量、高效 (lightweight and efficient)
node.js是什么?
构建与Chorme V8 引擎之上的,JS运行时。包生态系统 (package ecosystem),npm(是个管理node.js资源的系统)是世界上最大的开源库生态系统
6、node必须要在终端环境下才能执行。
7、path环境变量
可以实现在终端中打开一个可执行文件
快速在终端中打开:shift + 鼠标右键-->在此处打开命令窗口-->输入要打开的文件名
实现在任意地方打开某一文件:
首先:我的电脑--右键属性--高级系统设置--系统属性--高级--环境变量
用户变量---PATH(如果没有可以新建)--PATH变量值路径与路径之间用英文逗号分隔。
8、console,log(__dirname) 当前文件模块所属目录的绝对路径
console.lgo(__filename) 当前文件模块的绝对路径
一般用于操作文件时用来进行绝对路径拼接
9、模块的缓存:
对于同一个模块标识,node在第一次加载完成之后就会缓存该模块,下次继续加载该模块的时候直接从缓存中拿。
模块的加载:
模块可以被多次加载,但是只会在第一次加载的时候运行一次,然后被缓存:目的是为了提高性能
nodejs模块加载的顺序是同步进行的(SeaJS中是预加载,懒执行)
node在执行到require的时候,才会同步的加载该文件(读取文件)
node是按照代码出现的顺序进行加载的
node的代码运行在服务器端
seajs中是预先加载好所有的js文件(不执行)等到所有的js文件加载完成才开始执行
seajs是预加载懒执行(一个文件加载成功之后并没有立即执行)
seajs预加载是为了防止在代码中出现动态加载而导致功能无法执行或者延迟执行
10、删除当前模块的缓存:
delete require.cache[module.filename]
------------->文件操作<--------------------------
1、文件写入--同步
同步方式写入文件:writeFileSync('./a.txt',''今天很开心") 同步代码会按照顺序执行,有利于程序员的编程思维逻辑
在进行文件操作的时候,如果是同步的API必须使用 try-catch 来捕获异常,防止程序因为异常退出,导致后续代码无法执行
案例:
var fs = require('fs');
try{
fs.writeFileSync('一个不存在的文件路径/a.txt',''今天很开心")
}catch(e){
console.log('不好意思,文件写入失败了');
}
2、文件写入--异步
异步方式写入文件;writeFile('./a.txt',"今天很开心",funtion(err){......}) 异步操作不会阻止后续代码执行
在异步操作API中是无法通过try-catch 来捕获异常的,基本上所有的异步操作 API,Node 内部都把错误对象传递给了回调函数的第一个参数
案例:
var fs = require('fs');
fs.writeFile('./a.txt',"今天很开心",funtion(err){
if ( err ) {
console.log('不好意思,文件写入失败了');
}
})
异步代码处理异常实现原理:
回调函数的第一个参数是默认几首错误信息,第二个参数才是真正的数据
强调错误优先:回调函数第一个参数为上一步错误信息,通过在回调函数中判断err是否为null来检测异步操作过程是否出错
3、文件追加
var fs = require('fs')
var data = ' \n 文件追加的内容 ' // 给./a.txt 文件追加data 中的内容
fs.appendFile('./a.txt',data,function(err){
if(err){
return console.log('文件追加失败') // 使用return 的方式,出错后回调函数的代码将不再往后执行
}
console.log('文件追加成功')
})
4、读取文件
var fs = require('fs')
fs.readFile('路径',function(err,data){
if(err){
return console.log('文件读取失败')
}
console.log(data.toString()) // data是读取出的数据,是计算机中保存的二进制数据(十六进制)
)
5、Nodejs中npm常用命令:
npm(node package manager)node包管理器,主要功能:安装、卸载、更新、查看、搜索、发布等
http://www.npmjs.com //查询一些包以及包的一些信息
查看是否有 npm :cmd中输入 npm -v 如果有npm版本信息,则就可以使用
npm istall <name> -g 将nodejs的依赖包安装到全局环境中---->npm install -g less 安装less到nodejs管理包中
npm remove <name> 移除
npm update <name> 更新
npm ls 列出当前安装的所有包
npm root [-g] 查看当前包(全局)的安装路径
npm help [install] 帮助(查看install命令的帮助)
6、模块标识可以省略后缀名
Node会按照'.js'、'.json'、'.node' 进行查找加载
'.js'会按照js解析器解析并执行
'.json'会以JSON格式文本进行解析 当请求的资源文件,匹配到 .json 文件,那么就会默认通过 JSON.parse(str) 将该文件直接转换并返回转换后的对象
'.node'会以编译后的二进制文件进行解析
7、模块的循环加载
如果发生循环依赖,可能发生得不到完整的数据的结果:
a.js
console.log('a.js文件被加载')
exports.foo = 'aaa'
var foo = require('./b')
console.log(foo)
exports.foo = 'aaaaaa'
b.js
console.log('.b.j文件被加载')
exports.foo = 'bbb'
var foo = require('./a')
console.log(foo)
exports.foo = 'bbbbbb'
node.js是同步执行,sea.js是异步执行
8、require得到的是值的拷贝
在模块中,一旦输出一个值,模块内部的变化就影响不到这个值
a.js
var fooModule = require('./b.js') // require 得到的实际上指的是拷贝,如果在被加载的模块中动态修改数据值是根本不起效果的
console.log(fooModule.foo) // bar
fooModule.changeFoo()
console.log(fooModule.foo) // bar
b.js
console.log(arguments)
var foo = 'bar'
exports.foo = foo
exports.changeFoo = function (){
foo = 'baz'
console.log(foo) // baz
}
9、require实现原理:(实现:MyRequire)
首先读取要被加载的文件模块内容(字符串(js代码))
然后通过类似于eval的一个函数去解析和执行读取到的js字符串代码
最后得到该代码中暴漏的 module.exports 对象接口
Myrequire.jsvar fs = require('fs')var data = fs.readFileSync('./foo.js').toString()var packStr = '(function(exports,module){'+data+' return module.exports})'var func = eval(packStr)var module = {exports : {}}console.log(func(module.exports,module))foo.jsvar a = 1exports.a = a
10、Buffer:用来创建一个专门存放二进制数据的缓存区
Buffer是Node原生提供的全局对象,可以直接使用,不需要 require
Buffer与字符串之间的转换:
buffer实例对象.toString()--->转为字符串
Buffer支持的编码:
ASCII
UTF8
UTF16LE
UCS2(UTF16LE的别名)
Base64 图片
Binary
Hex 将每个字节编译成为两个十六进制字符
Buffer构造方法:
new Buffer(size)
new Buffer(str [ , encoding ] )
Buffer实例属性--大小:
buf.length
Buffer实例方法:
buf.write()
buf.toString() 将一个buffer二进制对象转换为字符,默认编码是utf8
Buffer的类方法
Buffer.inEncoding() 用来判断是否支持该编码类型
Buffer.isBuffer() 用来判断是否是一个Buffer类型对象
Buffer.byteLength() 用来计算一个字符串对应的编码所占用的字节大小
Buffer.concat(数组[,totalLength]) 可以将多个buffer对象拼接为一个完整的buffer对象
11、路径拼接
var fs = require('fs')
var path = require('path')
//如果在终端执行的时候,node 执行命令所处的路径不是当前文件模块所属的目录,那么在读取文件的时候所指定的 相对静态资源路径 就会相对于 node 命令所处的目录,为了避免错误,我们以后在执行带有路径文件操作的时候,直接进入当前文件模块所属的目录执行,因此在操作文件路径的时候,都使用绝对路径
//但是 require 模块标识相对路径不受 node 命令所处路径的影响
fs.requireFile(path.join(__dirname,'b.txt'),funtion(err,data){
if(err){
throw err
}
console.log(data)
})
12、Node调试
使用node内置调试器:[官方调试文档](https://nodejs.org/dist/latest-v6.x/docs/api/debugger.html)
node debug ./foo.js
进入调试状态 debug >
命令: help ----> 查看常用命令
next(简写:n)---->下一步
quit ---->退出调试环境
cont 继续下一个断点
repl 从调试模式进入 REPL 运行环境 (按 Ctrl + c 可以退出 RPEL 回到调试模式)
按下 enter 可以重复执行上一次输入的调试命令
watch ('my_expression') 监视变量
unwatch('my_expression') 取消监视变量
step,s - Step in 步进
step,o - Step out 步出
使用vsc(visual studio code)调试 node
-1、在 vsc 里面,以项目的方式打开一个目录
单独的文件是无法进行调试的
-2、打开要调试的js文件
-3、在要调试的地方左边 点击 设置一个红色的断点
-4、然后按 F5 启动调试,在弹出的提示框选择调试环境:Node.js
-5、选择了 node.js 之后,vsc 会自动在当前项目目录下生成一个 .vscode 目录
同时在 ' .vscode ‘ 目录下自动创建一个叫做:'launch.json' 的文件
-6、在 'launch.json' 文件中找到 configurations 属性 下面的 program 该属性
'program' 属性中的 ${workspaceRoot} 就表示当前项目根目录
在 app.js 处修改为 该项目的启动 文件名。
-7、配置完要调试的具体文件路径之后,按 F5 启动调试
如果启动不成功,提示找不到要启动调试的文件,那就点击树状菜单栏中的小蜘蛛图标,切换掉调试面板,然后点击左上角 绿色的 开始调试按钮
-8、调试就开始了
13、文件其他相关操作
读取文件、写入文件、向文件中追加内容、获取文件信息 stat 、删除文件、验证路径是否存在、重命名文件、移动文件、监视文件变化
获取文件信息:
fs.stat(path,function(err,stats){
if(err)
throw err
console.log(stats) //data是一个 fs.Stats对象
})
stats对象属性:
{
dev: 1651831854,
mode: 33206,nlink: 1,uid: 0,gid: 0,rdev: 0,blksize: undefined,ino: 13792273858845704, //文件的唯一size: 362, //文件大小blocks: undefined,atime: 2016-06-14T13:06:52.483Z, //access time 最后一次使用mtime: 2016-06-14T13:58:49.084Z, // modified time 最后一次修改文件内容时间ctime: 2016-06-14T13:58:49.084Z, // change time 最后一次修改文件信息的时间birthtime: 2016-06-14T13:06:52.244Z // birth time 文件的创建时间}
stats对象的方法:
stats.isFile() //判断传入的path 是不是文件
stats.isDirectory() //判断传入的 path 是不是目录
删除文件:
重命名文件:
fs.rename(oldPath,newPath,callback) //callback 没有推荐参数
fs.renameSync(oldPath,newPath)
读取目录:
fs.readdir(dirpath,function(err,files){
if(err){
throw err
}
console.log(files)
})
监视文件:
//监视文件执行之后,程序会保持挂起状态,监视文件变化,当文件发生变化时执行 listener 函数
fs.watchFile(filename [,options ] ,listener)
options <Object>
persistent 永久的,Boolean
interval 间隔,Integer整数
例如:{ persitent : true , interval 5007 } //默认5007ms后执行
listener <Function> 当文件在任何时间被使用的时候调用
例如:function(cuur,prev){......} // current stat object , previous stat object
14、path对象
var path = require('path') //创建path对象
方法:
path.extname(路径) //获取文件的扩展名部分
path.extname('index.html')// returns '.html'path.extname('index.coffee.md')// returns '.md'path.extname('index.')// returns '.'path.extname('index')// returns ''path.extname('.index')// returns ''
path.dirname(路径) //获取文件所在的目录
path.dirname('/foo/bar/baz/asdf/quux')
// returns '/foo/bar/baz/asdf'
path.basename(路径[,extendname]) //获取文件名
path.basename('/foo/bar/baz/asdf/quux.html')
// returns 'quux.html'
path.basename('/foo/bar/baz/asdf/quux.html', '.html')
// returns 'quux'
path.delimiter //定界符
unix:
console.log(process.env.PATH)
// '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin'
process.env.PATH.split(path.delimiter)
// returns ['/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/bin']
window:
console.log(process.env.PATH)// 'C:\Windows\system32;C:\Windows;C:\Program Files\node\'process.env.PATH.split(path.delimiter)// returns ['C:\\Windows\\system32', 'C:\\Windows', 'C:\\Program Files\\node\\']
path.format( pathObject ) //路径格式化,获得属性值按顺序拼接的结果
path.format({
dir: '/home/user/dir',base: 'file.txt'});// returns '/home/user/dir/file.txt'path.format({root : "C:\\",dir : "C:\\path\\dir",base : "file.txt",ext : ".txt",name : "file"})// returns 'C:\\path\\dir\\file.txt'
path.isAbsolute(路径) //判断路径是否是绝对路径
path.isAbsolute('//server') // true
path.isAbsolute('C:/foo/..') // truepath.isAbsolute('bar\\baz') // falsepath.isAbsolute('.') // false
path.join([path1],[path2],[,.....]) //拼接路径
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..')// returns '/foo/bar/baz/asdf' //加上两个点,表示拼接到当前目录的上级目录
path.join('/foo', 'bar', 'baz/asdf', 'quux')// returns '/foo/bar/baz/asdf/quux
path.join('/foo', 'bar', 'baz/asdf', 'quux','.')// returns '/foo/bar/baz/asdf/quux //加一个点,表示拼接到当前目录path.parse(路径) //路径解码
path.parse('C:\\path\\dir\\index.html')// returns// {// root : "C:\\",// dir : "C:\\path\\dir",// base : "index.html",// ext : ".html",// name : "index"// }
--------------------------------Node使用第三方包------------------------------------------
目的:使用别人做好的一些功能,然后在具体的代码的地方去加载这个包,可以辅助项目功能的开发
1、node官网--->npm-->搜索相应的包--->githup...仓库地址--->下载--->引入项目中-->找该包的入口文件:
在该包目录下找 package.json 文件
在 package.json 文件中,找 main 属性,main属性保存的是文件的入口模块
2、使用npm工具进行下载安装
在当前项目目录下 npm install 包名 + 回车 安装过程必须联网
安装成功:
下图是安装 markdown 成功后显示的界面:
安装成功后, node 会自自动在当前项目的根路径下创建一个目录叫做:node_modles ,然后把第三方包自动放到该目录下。该目录是专门用来防止第三方包的!所有内容最好不要修改!
3、使用该包:
使用 require 加载第三方包
对于第三方包来说,在 require 方法的模块标识应该输入 npm install 时候的包名
4、什么是包?
包描述文件中的 dependencies 是一个非常重要的字段,可以和 npm 工具结合起来使用
当我们执行 'npm install'命令的时候,npm 工具自动在当前执行命令的目录下找 package.json文件,如果找到,把里面的 dependencies 字段里面的值拿出来,然后依次下载(联网状态)
如果想要把项目托管到 github 上,那么就不要把 node_module 目录放到源码中。对于一些第三方依赖的包让用户自己下载即可。
5、包的加载规
对于 require 模块标识来说
文件模块:以/ ../ / 开头的标识符、
核心模块:不以 ./ ../ / 开头的标识符、
特殊的文件模块即包模块:既不是文件模块标识也不是核心模块标识,但是 node.js 默认会把它当成核心模块进行加载,如果 node 在加载的过程中发现 标识符名 不是核心模块,到当前文件所属目录下找 node_modules ,目录下找有没有一个叫做 该模块标识的,如果找到了 该标识名 的子目录,那么 node 会找该子目录下的一个叫做 package.json 的文件,如果找到了 package.json 文件,那么该文件中的一个属性 main ,得到里面的值,然后根据 main 的值指定的路径进行加载(这样做的好处:用户在使用第三方包的时候再也不用关心这个包的入口模块是哪个文件了)
如果 node 在当前目录下的 node_modules 目录下找不到,该模块标识的 目录,那么node 会自动进入上一级目录下,找上一级目录下有没有一个叫做 node_module的目录,如果找到按照上面的规则进行加载,如果找不到则继续往上查找,直到到达根路径,若还未找到则进行报错
6、npm的基本使用(二)
在加载第三方包的时候最好使用:npm install 报名 --save 自动将依赖项添加到 package.json 的 dependencies 字段上(--save 可以在包名前面,也可以在包名后面)
npm uninstall 包名 --save 卸载包,并在 dependencies 依赖上删除依赖
7、安装一些全局命令工具行
使用 npm 也可以安装一些命令终端下的一些工具,例如类似于 npm 这样的工具
安装方式:
npm install http-server -g //安装 http-server 命令行工具到全局目录下
查看全局命令行安装的目录:
npm root -g
8、本地安装目的是为了在代码中具体的辅助我们进行功能开发
全局安装目的是为了把要安装的这个包当做一个全局命令行下的工具来使用
9、解决 npm 被墙的问题
因为 npm 的镜像源都在国外,所以国外的网站......
国内的淘宝做了一个 npm 镜像:搜索 cnpm-淘宝 npm 镜像
安装 cnpm 到全局命令行终端下:
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnmp 和 npm 的命令一致
如果不想安装 cnpm 可以自己手动指定镜像源:
nrm (node registry management) 镜像源地址管理工具,它也是一个基于 node 开发的一个全局命令行工具
安装完之后就可以在终端的任何路径下使用 nrm 命令来管理镜像源地
使用:
nrm 查看使用帮助
nrm ls 显示所有可用的镜像源
nrm current 显示当前所使用的镜像源名字
nrm use 镜像源名称,可以用来切换镜像源地址
10、npm发布
注册npm账号:
npm adduser 执行该命令,依次输入用户名、密码、Email,等待注册成功即可
因版本太低导致发布不成功:
sudo npm install -g npm
发布程序包:
npm publish <本地路径>
更新程序包:
只需要修改 package.json的版本号即可
取消发布内容:
npm unpublish 包名@版本号
----------------------------->文件流(处理大文件)<-----------------------------------------
使用:
var fs = require('fs')
1、创建一个可读流
var rs = fs.createReadStream(读取文件路径)
2、创建一个可写流
var ws = fs.createWriteStream('写入文件的路径')
3、监听可读流的 data 事件,然后将 data 事件的回调函数中的数据写到可写流当中
方法1:
rs.on('data',function(chunk){ws.write(chunk)})
方法2--管子:pipe是一个高效的数据处理方式
rs.pipe(ws)
------------------------------------>FQCross Fire<----------------------------------------------
GFW(Great Firewal of China)中国国家防火墙
vpn
蓝灯lanrern:
---蓝灯官网
ShadowSocks:只是一个客户端软件
作业:
学习如何发布一个包到npm上
自学 bower(全局命令行工具)(是什么,解决什么问题,如何使用)
Bower与npm的区别:
Bower的安装和升级都会依赖于npm:npm install -g bower,bower的使用方式跟npm类似
npm主要运用于node.js项目的内部依赖包管理,安装的模块位于项目根目录下的node_modules文件内,在使用过程中主要针对后端开发(嵌套管理);
而Bower大部分情况下用于前端开发,对于CSS/JS模板等内容进行依赖管理,依赖的下载目录结构可以自定义( 扁平化管理)。
----------------------------->网络编程<-----------------------------------------
1、node只是一个可以帮助我们呢学习网络编程的一个工具,使用其他编程语言或者操作系统进行网络编程,思想都是一致的。
Node是一个面向网络而生的平台。
Node的目标是成为一个构建快速、可伸缩的网络应用平台。
每一个Node进程构成网络应用的一个节点,这就是Node的含义。Node诞生的目的就是为了更加高效得处理网络数据而诞生的。
服务器的本质目的:服务器本质就是一个计算机。
端口号是用来具体定义一个应用程序的。
2、Net:
-1、加载net
var net = require('net')
-2、使用net核心模块创建一个服务器
var server = net.createServer() //通过调用 createServer() 方法创建一个服务器对象
-3、设置监听客户端的连接请求事件处理
server.on('connection',function(){
})
-4、启动服务器
server.listen(端口号)
3、查看自己的IP地址:ipconfig 在linux和mac:ifconfig
4、Socket网络编程:
-1、创建服务器:
var net = require('net')var server = net.createServer();server.on('connection',function(socket){socket.on('data',function(data){console.log('客户端说:'+data.toString())socket.write('服务器对客户端说:你猜......')}socket.on('error',function(){console.log('有客户端异常退出了')})})server.listen(3030)//connection链接事件只有第一次 客户端与服务器端 连接成功之后调用//server.listen('端口号','监听的IP','回调函数其实也就是listenning事件')
//当客户端和服务器连接成功之后,服务器会把客户端的ip地址和端口号封装为一个Socket对象,传递给connection方法的回调函数的第一个参数
//socket是一个双向流,可读可写,谁与服务器连接就是谁
//data就是接收到的客户端的消息,接收到的数据是二进制
//socket.write('......')向客户端发送数据
//server.on('listenning',function(){
//server.on('listenning',function(){
//})
-2、创建客户端
var net = require('net')
var client = net.createConnection({
port : 3030,
host : '服务器IP'
})
client.on('connect',function(){
console.log('客户端与服务器端连接成功了,可以进行通信了')
client.write('客户端对服务器说:请问你叫什么?') //每一次都会从 client 里面把端口号和 IP 拿出来,将消息发送出去
})
client.on('data',function(data){
console.log('服务器说:'+data.toString())
})
//host:服务器 IP 或者是 127.0.0.1 本机回环IP,这样的话即使在没有网的情况下也能进行 客户端与服务器 的通信,这时候本机就充当 客户端与服务器 这两个角色
//当客户端要与服务器连接通讯的时候,程序会自动为客户端分配一个端口号来与服务器通信
//客户端与服务器端什么时候连接成功无法确定(取决于带宽和端口号等),则通过connect事件来解决连接之后再处理事件
//data是接收到的服务器端的消息,接收到的数据是二进制
//client.write('......') 向服务器端发送数据
5、Socket对象:
socket.localAddress 服务器地址
socket.localPort 服务器端口号
socket.remoteAddress 客户端地址
socket.remoteFmaily 客户端IP簇:IPV4/IPV6
socket.remotPort 客户端端口号
socket.on('data',function(data){
console.log(data.toString().trim()) //输出从客户端返回的数据
})
socket.write() 客户端连接成功后,给客户端发送内容
scoket.on('error',function(){
console.log('有客户端异常退出了')
}) //当客户端异常的时候触发
6、全局命令行工具---解决每次编写完服务器程序之后都要重启服务器的问题
nodemon-----基于node.js的全局命令行工具
安装:npm install -g nodemon
使用:nodemon example.js
7、Global
process就是当前运行的程序或者说进程
获取用户输入:
process.stdin.on('data',function(data){
console.log(data.toString().trim()) //data就是获取到的用户输入的内容
})
//stdin(standard input)标准输入
process.version 进程的版本号
process.title 进程执行的窗口名称
8、在地址栏输入网址后页面是如何呈现的?
9、HTTP协议:
基于传输层之上的应用层的一种协议。
协议:就是约定出来双方共同遵守的内容。
OSI:(Open System Interconnection Reference Model)模型:开放式系统互联通信参考模型,简称OSI模型
一种概念模型,由国际化标准组织ISO提出。
一个试图使各种计算机再世界范围内互联网通信的标准框架、标准规范。
数据传输:
应用层HTTP传输层网络层数据链路层物理层
10、安装 curl 工具
curl -v 地址:端口号 //
11、web网络编程
请求报文:
响应报文:
12、浏览器本质.js
var net = require('net')
var server = net.createServer()
server.on('connection',function(socket){
socket.on('data',funtion(data){
console.log(data.toString())
socket.write('HTTP/1.1 200 OK \n\n hello world') //写请求头
scoket.end() //结束响应
})
})
在 浏览器 中查看;使用 curl 查看具体内容
13、http
var http = repuire('http')
var server = http.createServer() //创建一个 HTTP 服务器(其实就是一个 Socket 服务器)
//request 就是一个可读流,用来 获取 当前与服务器连接的客户端的一些请求报文数据
//response 就是一个可写流,用来给 客户端 Socket发送消息的,或者用来发送响应报文的
server.on('request',function(){
//console.log(有客户端进来了')
//对于 HTTP 请求响应模型来说,他们的每次请求和响应式一次性的。也就是说每次请求都必须结束响应
//HTTP 发送响应数据的时候,HTTP 服务器会自动把数据通过 HTTP 协议包装为一个响应报文的对象
response.write('hello world')
//在结束之前可以多次向 客户端 发送数据
response.write(''end)
//响应结束后 必须有结束响应的标志,否则浏览器会认为还没有把数据发送完成,就不能渲染出来
response.end()
//在一次HTTP请求响应模型中,当结束了响应,就不能继续发送数据,否则就会出现错误1提示的 45 5错误
})
server.listen(端口号,function(){
console.log('server is listening at port 3000')
})
错误1:
------通过请求路径访问:
server.on('request',function(request,response){
var url = request.url
if(url ==='/' ){
response.end('hello')
}else if(url === '/login'){
response.end('helo login')
}else{
response.end('404 not Fond!')
}
})
-------读取页面:
var fs = require('fs)
var path = require('path')
server.on('request',function(request,response){
var url = request.url
if(url ==='/' ){
fs.readFile(path.join(__dirname,'....html'),'utf-8',function(err,data){
if(err){
throw err
}
response.end(data)
})
}else if(url === '/login'){
...
}else{
response.end('404 not Fond!')
}
})
--------node 的 HTTP 模块天生就不具备处理静态资源请求的能力???
传统的 Apache 、tomcat、IIS 默认都为使用者处理了静态资源请求
------处理静态资源请求
var http = require('http')
var fs = require('fs')
var path =require('path')
var server = http.createServer()
server.on('request',function(req,res){
var url = req.url //端口号后面的请求文件的路径名
var fullpath = path(__dirname,url)
if(url==='/'){ //当没有输入路径的时候,默认让用户访问一个地址
fullpath = path(__dirname,'默认访问路径')
}
fs.readFile(fulPath,function(err,data){
if(err){
//在进行web 开发的时候,如果发生错误,可以直接把该错误消息输出给 客户端
return res.end(err.message)
}
res.end(data)
})
})
server.listen(端口号,function(){
console.lgog('服务已经启动......')
})
-----------------------------------------------------------------------------
查看文件对应的 ContentType 类型
根据不同 url 处理不同的内容
表单的提交处理:
如果表单中有上传的文件,必须指定 enctype="multipart/form-data";
没有指定 enctype 的情况下,可以在后台使用 qstring.parse(data) 处理表单以 post 方式传递过来的数据为 JSON 字符串。
处理以 post 方式提交文件的表单,可以使用社区的一个包:formidable //查看 npm 官网,查看包的例子
安装包:npm install --save formidable
查看并使用包的相关方法
表单内容提交成功后跳转:
res.writeHead(302,{'Location:'跳转的地址''})
res.end()
学习、交流、记录、编辑一部自己的知识库