Nodejs开发技巧
- 下载与资源
- Nodejs安装
- npm
- Node.js的概念
- fs模块
- 写文件
- 核心模块os和path
- http模块
- 模块的导出与导入
- 第三方模块导入规则
- nodemon自动重启
- Express
- express-generator
- art-template模板
- body-parser
- express-router
- forever守护进程
- 回调函数callback
- 操作MongoDB
- 跨域
下载与资源
Nodejs官网 |
文档 |
中文社区 |
webstorm |
代码规范 |
npm |
cnpm |
express |
HapiJS开发手册
Nodejs安装
//windows
直接下载安装
//ubuntu
利用nvm: https://github.com/nvm-sh/nvm
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
// 注意,运行代码之后需要重新打开终端。
// 重新打开终端并输入nvm,即可看到nvm已经可以使用了。
nvm ls-remote --lts 以列出所有的LTS版本node。
nvm install --lts 自动安装最新LTS版本的node(Latest LTS Version: 12.16.1 (includes npm 6.13.4))
node -v
//v12.16.1
npm -v
//6.13.4
npm
1、npm init -y //初始化安装
2、npm install 包名 –-save //下载并保存依赖项(package.json)
npm i –S //简写
npm update express //更新
3、npm uninstall 包名
4、npm help npm init --help
5、npm config set registry https://registry.npm.taobao.org //把淘宝镜像设成默认
npm config list //查看配置信息
(npm install –global cnpm /切换到淘宝镜像工具
npm install 包名 --registry=https://registry.npm.taobao.org //直接使用淘宝镜像源)
registry = https://registry.npmjs.org/ //官方默认源
6、nodemon //自动重启服务器
npm install nodemon --global
node app.js => nodemon app.js
Node.js的概念
- JavaScript 运行时。既不是语言,也不是框架,它是一个平台。
- Node.js 中的 JavaScript
- 没有 BOM、DOM
- 在 Node 中为 JavaScript 提供了一些服务器级别的 API
- 文件操作的能力
- http服务的能力
- EcmaScript
- 变量
- 方法
- 数据类型
- 内置对象
- Array
- Object
- Date
- Math
- 模块系统
- 在 Node 中没有全局作用域的概念
- 在 Node 中,只能通过 require 方法来加载执行多个 JavaScript 脚本文件
- require 加载只能是执行其中的代码,文件与文件之间由于是模块作用域,所以不会有污染的问题
- 模块完全是封闭的
- 外部无法访问内部
- 内部也无法访问外部
- 模块作用域固然带来了一些好处,可以加载执行多个文件,可以完全避免变量命名冲突污染的问题
- 在每个模块中,都提供了一个对象:
exports (modole.exports)
,该对象默认是一个空对象 - 需要被外部访问使用的成员手动的挂载到
exports
接口对象中
- 核心模块
- 核心模块是由 Node 提供的一个个的具名的模块,它们都有自己特殊的名称标识,例如
- fs 文件操作模块
- http 网络服务构建模块
- os 操作系统信息模块
- path 路径处理模块
- 所有核心模块在使用的时候都必须手动的先使用
require
方法来加载,然后才可以使用,例如:var fs = require('fs')
- 核心模块是由 Node 提供的一个个的具名的模块,它们都有自己特殊的名称标识,例如
- http
- require
- 端口号
- ip 地址定位计算机
- 端口号定位具体的应用程序
- Content-Type
- 服务器最好把每次响应的数据是什么内容类型都告诉客户端,而且要正确的告诉
- 不同的资源对应的 Content-Type 是不一样,具体参照:http://tool.oschina.net/commons
- 对于文本类型的数据,最好都加上编码,目的是为了防止中文解析乱码问题
// 在 http 协议中,Content-Type 就是用来告知对方我给你发送的数据内容是什么类型
// res.setHeader('Content-Type', 'text/plain; charset=utf-8')
- 通过网络发送文件
- 发送的并不是文件,本质上来讲发送是文件的内容
- 当浏览器收到服务器响应内容之后,就会根据你的 Content-Type 进行对应的解析处理
fs模块
浏览器中的 JavaScript 是没有文件操作的能力的,但是 Node 中的 JavaScript 具有文件操作的能力。
fs 是 file-system 的简写,就是文件系统的意思。在 Node 中如果想要进行文件操作,就必须引入 fs 这个核心模块。
//使用 require 方法加载 fs 核心模块
var fs = require('fs')
//读取文件
第一个参数就是要读取的文件路径
第二个参数是一个回调函数
成功
data 数据
error null
失败
data undefined没有数据
error 错误对象
fs.readFile('./data/a.txt', function (error, data) {
// <Buffer 68 65 6c 6c 6f 20 6e 6f 64 65 6a 73 0d 0a>
// 文件中存储的其实都是二进制数据 0 1,这里是16进制
// 所以我们可以通过 toString 方法把其转为我们能认识的字符
console.log(data.toString())
})
写文件
var fs = require('fs')
// 第一个参数:文件路径
// 第二个参数:文件内容
// 第三个参数:回调函数
// 成功:
// 文件写入成功
// error 是 null
// 失败:
// 文件写入失败
// error 就是错误对象
fs.writeFile('./data/你好.md', '大家好,给大家介绍一下,我是Node.js', function (error) {
// console.log('文件写入成功')
// console.log(error)
if (error) {
console.log('写入失败')
} else {
console.log('写入成功了')
}
})
核心模块os和path
// 用来获取机器信息的
var os = require('os')
// 用来操作路径的
var path = require('path')
// 获取当前机器的 CPU 信息
console.log(os.cpus())
// memory 内存
console.log(os.totalmem())
// 获取一个路径中的扩展名部分
// extname extension name
console.log(path.extname('c:/a/b/c/d/hello.txt'))
http模块
// ip 地址用来定位计算机
// 端口号用来定位具体的应用程序
// 所有需要联网通信的应用程序都会占用一个端口号
var http = require('http')
var server = http.createServer()
// 2. 监听 request 请求事件,设置请求处理函数
server.on('request', function (req, res) {
console.log('收到请求了,请求路径是:' + req.url)
console.log('请求我的客户端的地址是:', req.socket.remoteAddress, req.socket.remotePort)
res.end('hello nodejs')
})
server.listen(3000, function () {
console.log("服务器启动成功,端口号3000, http://127.0.0.1:3000")
})
模块的导出与导入
//导出的变量和函数,都在exports对象中
//可以默认为每个模块中都有一个modole对象,
//modole.exports = exports
var foo = 'bbb'
exports.foo = 'hello'
exports.add = function (x, y) {
return x + y
}
//导出一个默认的变量或方法
modole.exports = "hello"
//导入
// require 方法有两个作用:
// 1. 加载文件模块并执行里面的代码
// 2. 拿到被加载文件模块导出的接口对象, exports
var bExports = require('./b')
console.log(bExports.foo)
console.log(bExports.add(10, 30))
第三方模块导入规则
凡是第三方模块都必须通过 npm 来下载
使用的时候就可以通过
require
('包名') 的方式来进行加载才可以使用不可能有任何一个第三方包和核心模块的名字是一样的
先找到当前文件所处目录中的 node_modules 目录
node_modules/art-template
node_modules/art-template/package.json 文件
node_modules/art-template/package.json 文件中的 main 属性
main 属性中就记录了 art-template 的入口模块
如果 package.json 文件不存在或者 main 指定的入口模块是也没有
则 node 会自动找该目录下的 index.js,也就是说 index.js 会作为一个默认备选项
如果以上所有任何一个条件都不成立,则会进入上一级目录中的 node_modules 目录查找。如果上一级还没有,则继续往上上一级查找。如果直到当前磁盘根目录还找不到,最后报错:can not find module xxx
nodemon自动重启
npm install nodemon --global
nodemon --version
nodemon app.js
Express
cnpm install express -–save
//app.js
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('hello world')
})
app.listen(3000, function () {
console.log('express running http://127.0.0.1:3000')
})
// 基本路由
请求方法,请求路径,请求处理函数
app.get('/', function(req, res){
res.send('hello world!')
})
app.post('/', function(req, res){
res.send('get a post')
})
// 请求静态资源
app.use('/public/', express.static('./public/'))
也可以省略前面的参数(路径不用写public):
app.use(express.static('./public/'))
//get获取参数
app.get('/post', function(req, res){
console.log(req.query)
})
//跳转
res.redirect('/')
express-generator
cnpm install express-generator -g
express book_service
cd book_service
cnpm install
SET DEBUG=book-service:* & npm start
// node bin/www
art-template模板
cnpm install --save art-template
cnpm install --save express-art-template
//app.js
var express = require('express')
var app = express()
app.engine('html', require('express-art-template')) //配置模板引擎
app.get('/', function (req, res) {
res.render('index.html', {})
//默认渲染 views中的文件
//req.query 得到get的请求体
})
app.listen(3000, function () {
console.log('aoo running http://127.0.0.1:3000')
})
body-parser
在Express中获取POST请求, 请求参数在req.body
中
cnpm install --save body-parser
//app.js
var bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false}))
app.use(bodyParser.json())
app.post('/register', async function(req, res){
console.log('register123', req.body)
let result = await create_account(req.body.username, req.body.password)
if(result === "ok"){
//创建成功
res.send('ok')
}else{
res.send(result)
}
})
express-router
//app.js
var router = require('./router')
// 把路由容器挂载到 app 服务中
app.use(router)
//router.js
// 专门用来包装路由的
var express = require('express')
// 1. 创建一个路由容器
var router = express.Router()
router.get('/students/new', function (req, res) {
res.render('new.html')
})
forever守护进程
$ sudo npm install forever -g //安装
$ forever start app.js //启动
$ forever stop app.js //关闭
$ forever start -l forever.log -o out.log -e err.log app.js //输出日志和错误
// 1. 简单的启动
//日志默认它会放到~/.forever/5er-.log
forever start app.js
forever list //查看列表
ps -aux | grep forever
// 2. 指定forever信息输出文件,当然,默认它会放到~/.forever/app.log
forever start -l app.log app.js
// 3. 指定app.js中的日志信息和错误日志输出文件,
// -o 就是console.log输出的信息,-e 就是console.error输出的信息
forever start -o out.log -e err.log app.js
// 4. 追加日志,forever默认是不能覆盖上次的启动日志,
// 所以如果第二次启动不加-a,则会不让运行
forever start -l forever.log -a app.js
// 5. 监听当前文件夹下的所有文件改动
forever start -w app.js
回调函数callback
- 一种数据类型
- 参数
- 返回值
- 一般情况下,把函数作为参数的目的就是为了获取函数内部的异步操作结果
- JavaScript 单线程、事件循环
//用回调函数获取异步的结果
function add(x, y, callback) {
console.log(1)
setTimeout(function () {
var ret = x + y
callback(ret)
}, 1000)
}
add(10, 20, function (ret) {
console.log(ret)
})
//eg:
fs.readFile('./data/tt.txt', function (error, data) {
console.log(data.toString())
})
// 注意:凡是需要得到一个函数内部异步操作的结果必须通过回调函数
// 例如: setTimeout,readFile,writeFile
操作MongoDB
跨域
app.all("*",function(req,res,next){
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin","*");
//允许的header类型
res.header("Access-Control-Allow-Headers","content-type");
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods","DELETE,PUT,POST,GET,OPTIONS");
if (req.method.toLowerCase() == 'options')
res.send(200); //让options尝试请求快速结束
else
next();
})