原生的http在某些方面表现不足以应对开发需求,需要使用框架加快开发效率,让我们的代码高度统一。
在node中很多Web开发框架,此处学习express为主
官网:http://expressjs.com/
安装
npm install --save express
hello world
//生成默认的package.json
//npm init -y
var express = require('express')
var app = express()
app.get('/',function (req,res) {
res.send('hello world')
})
app.listen(3000,function () {
console.log('express app is running')
})
什么是路由(router)?
作为分发的。路由其实就是一张表,表中存储着具体的映射关系。
当请求’/xxx’的时候,执行后面对应的function
路由器
get:
//当你以GET方法请求/的时候,执行对应的处理函数
app.get('/',function (req,res) {
res.send('hello world')
})
app.get('/login',function (req,res) {
res.send('login page')
})
post:
//当你以POST方法请求/的时候,执行对应的处理函数
app.post('/',function (req,res) {
res.send('Got a Post request')
})
//直接访问public中的资源
app.use(express.static('./public'))
//必须是/a/public目录中的资源具体路径,就是给public起了个别名叫a
//也就是use中第一个参数是在浏览器输入的url,第二个参数是实际的指定的目录名字
app.use('/a/',express.static('./public/'))
//大多数用的方式
//当以/public/开头的时候,去./public/目录中找对应的资源
app.use('/public/',express.static('./public'))
安装
npm install --save art-template
npm install --save express-art-template
配置
//配置使用art-template模板引擎
//第一个参数表示当渲染以.art结尾的文件的时候,使用art-template模板引擎
//express-art-template是专门用来在Express中把art-template整合到Express中
//虽然我们在这没有需要用到art-template,但是express-art-template依赖了它,所以也要安装一下
// app.engine('art',require('express-art-template'))
app.engine('html',require('express-art-template'))
使用
//Express为Response响应对象提供了一个方法:render
//render方法需要配置模板引擎才能使用
//res.render('html模板名',{模板数据})
//第一个参数不能写路径,默认会去views目录中查找该模板文件
//Express默认认为开发人员把所有的视图文件都放到views中
//如果想修改默认的views目录,可以用app.set('views',render函数的默认路径)
app.get('/',function (req,res) {
res.render('404.html')
})
修改视图目录路径v
//第一个参数表示需要修改views,第二个参数给出路径
app.set('views',render函数的默认路径)
使用第三方命名航工具 nodemon
来帮助我们解决频繁修改代码重启服务器问题,它是一个基于nodejs开发的第三方命令行工具,需要独立安装:
//在任意目录执行该命令都可以,因为是配置全局的
npm install --global nodemon
使用
//原来执行
node app.js
//使用nodemon
nodemon app.js
只要是通过nodemon app.js
启动的服务,它会监视文件变化,文件发生变化时自动重启服务器
Express内置了req.query来使用
req.query
Express中没有内置获取表单POST请求体的API,只能结合插件body-parser
实现
安装
npm install --save body-parser
配置
//引包
var bodyParser = require('body-parser')
//只要加入这个配置,则在req请求对象上会多出来一个属性:body
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
使用
app.use(function(req.res){
})
安装
npm i -S mongoose
demo
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test', {useNewUrlParser: true, useUnifiedTopology: true});
//设计一个模型,即设计一个数据库
//
var Cat = mongoose.model('Cat', { name: String });
//实例化一个Cat
var kitty = new Cat({ name: 'Zildjian' });
//持久化保存kitty实例
kitty.save().then(() => console.log('meow'));
启动mongod
连接mongo
退出连接exit
关闭打Ctrl+C或者直接关闭服务窗口
查看显示所有数据库show dbs
切换到指定数据库,如果没有,会自动创建出来use 数据库名称
查看当前操作的数据库db
插入数据db.集合名.InsertOne({"属性名":"属性值"})
查询所有
//查询所有
User.find({username:'admin'},function (err,ret) {
if(err){
console.log('查询失败')
}else{
console.log('查询成功')
console.log(ret)
}
})
单个查询
//条件查询
//第一个参数是条件,返回的是查到的第一个
User.findOne({username:'admin'},function (err,ret) {
if(err){
console.log('查询失败')
}else{
console.log('查询成功')
console.log(ret)
}
})
根据条件删除所有
//删除数据
User.remove({
username:'admin'
},function (err,ret) {
if(err){
console.log('删除失败')
}else{
console.log('删除成功')
console.log(ret)
}
})
根据条件删除一个
Model.findOneAndRemove(条件,[options],[callback])
根据ID删除一个
Model.findByIdAndRemove(id,[options],[callback])
安装npm i -S socket.io
//引包
var app = require('express')()
var server = require('http').Server(app)
var io = require('socket.io')(server)
如果我服务端要获取浏览器的数据,则在服务端注册一个事件,等待浏览器触发;
如果浏览器需要获取服务端的数据,则在浏览器注册一个事件,等待服务端触发。
//注册
//第一个参数是事件名,可以随便取;
//第二个参数是获取到的数据
socket.on('hehe',data=>{
console.log(data.msg)
})
//触发
//第一个参数是事件名
//
socket.emit('hehe',{
msg:'hello'
)
函数 | 描述 |
---|---|
JSON.parse() | 用于将一个 JSON 字符串转换为 JavaScript 对象。 |
JSON.stringify() | 用于将 JavaScript 值转换为 JSON 字符串。 |
文件操作路径:
//在模块加载中,相对路径中的./不能省
//如果不加的话,会去整个磁盘的根目录找,本文件磁盘根目录是E:/
// ./data是相对与当前目录的
// data 也是相对于当前目录
// ./data是绝对路径
// fs.readFile('./data/a.txt',function (err,data) {
//
// if(err){
// console.log('读取失败')
// }
//
// console.log(data.toString())
//
// })
模块操作路径:
//require也不能省.
require('./data/foo')
//如果忽略了. 则是当前文件绝对路径
require('/data/foo')
这是js带有的,不是node导致的。这种情况必须通过回调函数
回调
//形参名一般叫call
function(x,y,callback){
setTimeout(function(){
var ret = x+y
callback(ret)
},1000)
}
//上层定义一个
add(10,20,function(ret){
console.log(ret)
})
promise
Promise基础语法:
var fs = require('fs')
//p1是一个承诺实例
var p1 = new Promise(function (resolve, reject) {
fs.readFile('./data/a.txt', 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
p1
.then(function (data) {
console.log(data)
}, function (err) {
console.log('读取文件失败了', err)
})
Promise解决回调地狱
var fs = require('fs')
var p1 = new Promise(function (resolve, reject) {
fs.readFile('./data/a.txt', 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
var p2 = new Promise(function (resolve, reject) {
fs.readFile('./data/b.txt', 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
var p3 = new Promise(function (resolve, reject) {
fs.readFile('./data/c.txt', 'utf8', function (err, data) {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
p1
.then(function (data) {
console.log(data)
// 当 p1 读取成功的时候
// 当前函数中 return 的结果就可以在后面的 then 中 function 接收到
// 当你 return 123 后面就接收到 123
// return 'hello' 后面就接收到 'hello'
// 没有 return 后面收到的就是 undefined
// 上面那些 return 的数据没什么卵用
// 真正有用的是:我们可以 return 一个 Promise 对象
// 当 return 一个 Promise 对象的时候,后续的 then 中的 方法的第一个参数会作为 p2 的 resolve
//
return p2
}, function (err) {
console.log('读取文件失败了', err)
})
.then(function (data) {
console.log(data)
return p3
})
.then(function (data) {
console.log(data)
console.log('end')
})
Promise
Promise
+ http://es6.ruanyifeng.com/#docs/promise
+ callback hell 回调地狱
+ 回调函数中套了回调函数
+ Promise(EcmaScript 6 中新增了一个语法 API)
+ 容器
* 异步任务(pending)
* resolve
* reject
+ then 方法获取容器的结果(成功的,失败的)
+ then 方法支持链式调用
+ 可以在 then 方法中返回一个 promise 对象,然后在后面的 then 方法中获取上一个 then 返回的 promise 对象的状态结果