一、node简介
1、介绍
Node.js是一个JavaScript运行环境。实质上是对Chrome V8引擎进行了封装。Node.js对一些特殊用例进行优化,提供替代的API,使得V8在非浏览器环境下运行的更好。
V8引擎本身就是用于Chrome浏览器的JS解释部分,但是Ryan Dahl把这个V8搬到了服务器上,用于做服务器的软件。
Node.js是一个让JavaScript运行在服务器端的开发平台。它不是一种独立的语言,跟PHP、Python的“既是语言,也是平台”不同,Node.js使用JavaScript进行编程,运行在JavaScript引擎上(V8)。
与PHP、.net等后端语言相比,Node.js跳过了Apache、Nginx、IIS等HTTP服务器,它自己不用建设在任何服务器软件之上。Node.js没有Web容器。
Node.js自身的哲学是花最小的硬件成本,追求更高的并发,更高的性能处理。
Node.js官网地址:[https://nodejs.org/en/]
2、特点
-
单线程
- 优点:操作系统不用再有线程创建、销毁、的时间开销;
- 缺点:一个用户造成了线程的崩溃,整个服务器就崩溃了,其他人也就崩溃了
-
非阻塞I/O
- Node.js采用了非阻塞型I/O机制,比如在执行访问数据库代码的时候,会立即转而执行其后面的代码,把数据库返回结果的处理代码放在回调函数中,从而提高了程序的执行效率。
- 当某个I/O执行完毕时,将以事件的形式通知执行I/O操作的线程,线程执行这个事件的回调函数。为了处理异步I/O,线程必须有事件循环,不断的检查有没有未处理的事件,依次予以处理。
- 即请求和业务逻辑代码的执行互相不阻碍。
-
事件驱动 event-driven
- 在Node中,客户端请求建立连接,提交数据等行为,会触发相应的事件。在Node中,在一个时刻,只能执行一个事件回调函数,但是在执行一个事件回调函数的途中,可以转而处理其他事件(比如又有新用户连接了),然后返回继续执行原事件的回调函数,这种处理机制,称为“事件环”机制。
综上所述,单线程确保执行顺序不会混乱;非阻塞提高代码执行效率;事件驱动确保持续计算。缺一个就会导致运行问题的出现。
3、适合场景
当应用程序需要处理大量并发的I/O,而在向客户端发出响应之前,应用程序内部并不需要进行非常复杂的处理的时候,Node就很适合。Node也很适合和webscoket配合,开发长连接的实时交互应用程序。
比如:
- 用户表单收集
- 考试系统
- 聊天室
4、模块化
4-1、模块概念
我们的Node.js中,是以模块为单位划分所有功能,并且提供了一个完整的模块加载机制,这时我们可以将应用程序划分为各个不同的部分。我们不可能用一个js文件去写全部。
- 狭义的说,每一个JavaScript文件都是一个模块,而多个JavaScript文件之间可以互相require(请求、导入)。
- Node中,一个JavaScript文件中定义的变量、函数,都只在这个文件内部有效。如果需要从这个JS文件外部引用这些变量、函数时,必须使用exports对象进行暴露。而使用时要用require()命令引用这个JS文件。
4-2、模块的导入、导出
- require和module.exports
Node采用的是common.js的模块系统,导入模块用的是require这个全局函数,导出模块用的是module.exports的方式。一般写一个类时会用。
2.require和exports
使用exports导出一个exports对象,所有的变量、函数等,都在这个对象中,依然使用require进行导入。
可理解为exports = module.exports,两者不可一起用,不能将exports变量指向一个值,相当于切断了两者之间的联系
4-3、Module对象
Node内部提供一个Module构建函数。所有模块都是Module的实例。
每个模块内部,都有一个module对象,代表当前模块,它有以下属性:
- module.id 模块的标识符,通常是带有绝对路径的模块文件名。。
- module.filename 模块的文件名,带有绝对路径。
- module.loaded 返回一个布尔值,表示模块是否已经完成加载。
- module.parent 返回一个对象,表示调用该模块的模块。
- module.children 返回一个数组,表示该模块要用到的其他模块。
- module.exports 表示模块对外输出的值。
4-4、require指令
require命令的的基本功能是,读入并执行一个JavaScript文件,然后返回该模块的exports对象。如果没有发现指定模块,则会得到一个空对象。
- 引入时,使用了路径的话,require就会根据路径去寻找模块文件。
- 如果引入时没使用’./’、’/'开头,则表示加载的是一个默认提供的核心模块(位于Node安装的系统安装目录中),或者位于各级node_modules目录的已安装模块(全局安装或局部安装)。
5、npm
5-1、npm相关网站
NPM官网:[https://www.npmjs.com/]
NPM中文网:[https://www.npmjs.cn/]
淘宝NPM镜像:[https://developer.aliyun.com/mirror/NPM?from=tnpm]
淘宝NPM镜像安装方法:在cmd中执行此行命令安装cnpm,但总是会出现漏包的情况。npm不会漏包。cnpm即npm的国内版,npm在node安装时,已经安装好,而cnpm需要这样来安装:
··· npm install -g cnpm --registry=https://registry.npm.taobao.org ···
··· cnpm -v ```
使用某个模块或者包时,直接在cmd中使用npm install 即包名,install可简写为i.
5-2、package.json
我们使用package.json来管理依赖
在cmd中,我们可以使用npm init来初始化一个package.json文件,用回答问题的方式生成一个新的package.json文件。
npm init
快速创建:
npm init -y
使用一下命令能安装所有依赖
npm install
package.json介绍官网:[http://docs.npmjs.com/files/package.json]
5-3、npm常用命令
- 全局安装/卸载
npm install -g
npm uninstall -g
-g 代表全局
install 可简写为 i
- 包的安装
npm i 包名 --save-dev
同 npm i 包名 -D
可在包名后@版本号下载对应版本的包
package.json文件中devDependencies字段:
"devDependencies": {
"包名": "版本号"
}
- 运行
可在package.json文件中的scripts部分添加:
"scripts": {
"start": "包名或者js文件名"
}
运行时,可直接npm start
示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title></title>
<meta charset="UTF-8">
<style>
</style>
</head>
<body>
<form action="http://127.0.0.1:4000">
name: <input type="text" name="user" >
age: <input type="text" name="age" >
<input type="submit" value="提交">
</form>
</body>
</html>
let http = require('http')
let url = require('url')
let server = http.createServer(function(req,res){
//req.url可获取用户请求的url
// let path = req.url
//此处的运行要在html页面提交后,两段代码的端口相同。
//默认为get请求,简单拼接
let path = url.parse(req.url,true).query
//将提交的user和age单独拿出来
let user = path.user
let age = path.age
console.log(path)
console.log("用户名:"+user+",年龄:"+age)
//结果:[Object: null prototype] { user: '王一博', age: '18' }
// 用户名:王一博,年龄:18
// [Object: null prototype] {}
// 用户名:undefined,年龄:undefined
//至于为什么会有两个对象?会有两次请求,浏览器默认请求图标一次,是favicon.ico的请求
//要清除默认请求,可添加
if(path === "/favicon.ico"){
return
}
res.end()//http关闭
})
server.listen(4000)