其他
异步编程
- 函数也是一种数据类型,既可以当做参数进行传递,也可以当做方法返回值
- 一般情况下,把函数作为参数的目的就是为了获取函数内部的异步操作结果
- JavaScript 事件循环、单线程
- 回调函数
- console.log(‘1’)
setTimeout(function(){
console.log(‘2’)
},0)
console.log(‘3’)
# 执行结果:任何时候都是1,3,2,因为Js的单线程、事件循环机制
- console.log(‘1’)
- 不成立的情况:
- function add(x, y){
console.log(1)
setTimeout(function(){
console.log(2)
var ret = x + y
return ret
},1000)
console.log(3)
// 到这里执行结束,不会等到前面的定时器,所以直接就返回默认值undefined
}
console.log(add(10,20)) // => undefined
- function add(x, y){
- 不成立的情况
- function add(x, y){
var ret
console.log(1)
setTimeout(function(){
console.log(2)
ret = x + y
},1000)
console.log(3)
return ret
}
console.log(add(10,20)) // => undefined
- function add(x, y){
- 注意:凡是需要得到一个函数内部异步操作的结果,setTimeout,readFile,writeFile
- 回调函数
这是javascript编程的一大特色,异步编程。
- function add(x, y, callback){
// callback 就是回调函数
// var x = 10
// var y = 20
// var callback = function(a){}
console.log(1)
setTimeout(function(){
var ret = x + y
callback(ret)
},1000)
}
add(10, 20, function(a){
// a才是我们得到的结果
})
- function add(x, y, callback){
find/findIndex
find接收一个方法作为参数,方法内部返回一个条件,find会遍历所有的元素,执行你给定的带有条件返回值的函数,符合该条件的元素作为find方法的返回值,如果遍历结束还没有找到符合条件的元素,则范湖iundefined
8. MongoDB
8.1 关系型数据库和非关系型数据库
表就是关系或者说表与表时间存在关系。
- 所有的关系型数据库都需要通过sql语言来操作
- 所有的关系型数据库在操作之前都需要设计表结构
- 而且数据表还支持约束
- 唯一的
- 主键
- 默认值
- 非空
- 非关系想数据库非常的灵活
- 有的非关系型数据库就是key-value对
- 但是MongoDB是长得最像关系型数据库的非关系型数据库
- 数据库》数据库
- 数据库》集合(数组)
- 表记录》(文档对象)
- MongoDB是不需要设计表结构
- 也就是说可以任意的往里面存数据,没有结构性这么一说
8.2 安装
- 下载地址:
- 安装
- 配置环境变量
- 最后输入mongod –version测试是否安装成功
- 详细安装步骤:https://blog.youkuaiyun.com/yw00yw/article/details/81701774
8.3 启动和关闭数据库
启动:
# mongodb 默认使用执行 mongod 命令所处盘符根目录下的/data/db作为自己的数据存储目录
# 所以在第一次执行该命令之前先自己手动新建一个 /data/db
mongod
如果想要修改默认的数据库存储目录,可以:
mongod --dbpath=数据存储目录路径
停止:
在开启服务的控制台,直接Ctrl+c即可停止。
或者直接关闭开启服务的控制台也可以。
8.4 连接和退出数据库
连接:
# 该命令默认链接本机的 MongoDB服务
mongo
退出:
# 在链接状态输入 exit 退出连接
exit
8.5 基本命令
- show dbs
- 查看显示所有数据库
- db
- 查看当前操作的数据库
- use 数据库名称
- 切换到指定的数据(如果没有会新建)
- 插入数据
- db.students.insertOne({“name”:”jack”})
- 显示当前db 的所有集合
- show collections
- 查询当前db的所有数据
- db.students.find()
8.6 在Node中如何操作MongoDB数据库
使用官方的mongodb包来操作
http://mongodb.github.io/node-mongodb-native
使用第三方mongoose来操作MongoDB数据库
第三方包:mongoose基于MongoDB官方的mongodb包再一次做了封装。
- 网址 https://mongoosejs.com/
- 官方指南:https://mongoosejs.com/docs/guide.html
- 官方API文档:https://mongoosejs.com/docs/api.html
- 初始化项目
- cnpm init -y
- 安装mongoose
- cnpm i mongoose
- 连接操作
- # 引包
const mongoose = require(‘mongoose’);
# 连接 MongoDB 数据库
# 指定连接的数据库不需要存在,当你插入第一条数据之后就会自动被创建出来
mongoose.connect(‘mongodb://localhost/test’);
# 创建一个模型,就是在设计数据库
# MongoDB是动态的,非常灵活,只需要在代码中设计你的数据库就可以了
# mongoose这个包可以让你的设计编写过程变得非常简单
const Cat = mongoose.model(‘Cat’, { name: String });
# 实例化一个Cat
const kitty = new Cat({ name: ‘Zildjian’ });
# 持久化保持kitty实例
kitty.save().then(() => console.log(‘meow’));
- # 引包
8.7 MongoDB数据库的基本概念
- 数据库(可以有多个数据库)
- 集合(一个数据库中可以有多个集合)
- 文档(一个集合中可以有多个文档(表记录))
- 文档结构很灵活,没有任何限制
- MongoDB非常灵活,不需要像 MySQL一样先创建数据库、表、设计表结构
- 在这里只需要:当你需要插入数据的时候,只需要指定往哪个数据库的哪个集合操作就可以了
- 一起都由MongoDB来自动完成建库建表
{
qq:{
users:[
{name: ‘张三’, age: 12},
{}
],
products:[]
},
taobao:{},
baidu:{}
}
8.8 官方指南
设计Scheme发布Model
var mongoose = require('mongoose')
var Schema = mongoose.Schema
// 1. 连接数据库,连接本地的itcast数据库,该数据库可以不存在,自动创建
mongoose.connect('mongodb://localhost/itcast');
// 2. 设计集合结构(表结构)
// 字段名称就是表结构中的属性名称
// 约束的目的是为了保证数据的完整性,不要有脏数据
var userSchema = new Schema({
username: {
type: String,
required: true
},
password: {
type: String,
required: true
},
email: {
type: String
}
});
// 3. 将文档结构发布为模型
// mongoose.model方法就是用来将一个架构发布为model
// 第一个参数:传入一个大写名词单数字符串用来表示你的数据库名称
// 例如这里的User最终会变为users集合名称
// 第二个参数:架构Schema
// 返回值:模型构造函数
var User = mongoose.model('User',userSchema)
// 4. 当我们有了一个模型构造函数之后,就可以使用这个构造函数对User集合中的数据为所欲为了
module.exports =User
增加数据
var admin = new User({
username: 'admin',
password: '123345',
email: 'admin@qq.com'
})
admin.save(function(err,ret){
if(err){
console.log('保存失败');
}else{
console.log('保存成功')
console.log(ret)
}
})
查询
查询所有
User.find(function(err,ret){
if(err){
console.log('查询失败')
}else{
console.log(ret)
}
})
按条件查询所有
User.find({
username: '张三'
},function(err,ret){
if(err){
console.log('查询失败')
}else{
console.log(ret)
}
})
按条件查询单个数据
User.findOne({
username: 'admin',
password: 222
},function(err,ret){
if(err){
console.log('查询失败')
}else{
console.log(ret)
}
})
删除数据
User.remove({
username: 'admin'
},function(err,ret){
if(err){
console.log('删除失败')
}else{
console.log('删除成功')
}
})
# 根据条件删除一个
Model.findOneAndRemove(conditions,[options],[callback])
# 根据 id 删除一个
Model.findByIdAndRemove(id,[options],[callback])
更新数据
# 根据条件更新所有
Model.update(conditions,doc,[options],[callback])
# 根据指定的条件更新一个
Model.findOneAndUpdate([conditions],[update],[options],[callback])
# 根据id
User.findByIdAndUpdate('5b78008cfd7edbd6beda079c',{
password: '123'
},function(err,ret){
if(err){
console.log('更新失败')
}else{
console.log('更新成功')
}
})
8.9 nodejs连接mysql
- 安装
使用在npmjs.com中搜索即可
npm i mysql
使用
var mysql = require(‘mysql’);
// 创建连接
var connection = mysql.createConnection({
host : ‘localhost’,
user : ‘me’,
password : ‘secret’,
database : ‘my_db’
});
// 连接数据库
connection.connect();
// 执行数据操作
// connection.query(‘sql 语句’)
connection.query(‘SELECT 1 + 1 AS solution’, function (error, results, fields) {
if (error) throw error;
console.log(‘The solution is: ‘, results[0].solution);
});
// 关闭连接
connection.end();
9. Promise
9.1 callback hell:(回调地狱)
无法保证顺序的代码:
var fs = require('fs')
fs.readFile('./data/a.txt','utf8',function(err,data){
if(err){
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
});
fs.readFile('./data/b.txt','utf8',function(err,data){
if(err){
throw err
}
console.log(data)
});
fs.readFile('./data/c.txt','utf8',function(err,data){
if(err){
throw err
}
console.log(data)
});
通过回调嵌套的方式来保证顺序:
var fs = require('fs')
fs.readFile('./data/a.txt','utf8',function(err,data){
if(err){
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
fs.readFile('./data/b.txt','utf8',function(err,data){
if(err){
throw err
}
console.log(data)
fs.readFile('./data/c.txt','utf8',function(err,data){
if(err){
throw err
}
console.log(data)
});
});
});
为了解决以上的编码方式带来的问题(对调地狱嵌套),所有es6中新增了一个API,promise
9.2 Promise
Promise是一个构造函数
Promise容器,容器中存放了一个异步任务
Promise本身不是异步,但是内部往往都是封装了一个异步任务
Promise基本语法:
var fs = require('fs')
// 创建 Promise容器
// 1. 给别人一个承诺
// Promise 容器一旦创建,就开始执行里面的代码
var p1 = new Promise(function(resolve,reject){
fs.readFile('./data/a.txt', 'utf8', function(err,data){
if(err){
// 失败了,承诺容器中的任务失败了
// console.log(err)
// 把容器的Pending状态变为Rejected
// 调用reject就相当于调用了then的第二个回调函数
reject(err)
}else{
// 承诺容器中的任务成功了
// console.log(data)
// 把容器的Pending状态改为成功 Resolved
// 也就是说这里调用的resolve方法实际上就是then方法传递的那个function
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)
}
});
})
// p1 就是那个承诺
// 当 P1 成功了,然后then做指定的操作
// then方法接收的function就是容器中的resolve函数
p1.then(function(data){
console.log(data) //这是p1返回的数据
// 当p1读取成功时候
// 当前函数中return的结果就可以在后面的then中的function接收到
// 当你return 123 后面就接收到123,return什么后面就接收到的什么
// 真正有用的是:我们可以return一个promise对象
// 当return一个Promise对象的时候,后续的then中的方法的第一个参数会作为p2的返回值
return p2
},function(err){
console.log('读取文件失败了'+err)
})
.then(function(data){
console.log(data) // 这个方法就是作为p2的resolve
})
9.3 封装Promise版本的readFile
var fs = require('fs')
function pReadFile(filePath){
return new Promise(function(resolve,reject){
fs.readFile(filePath, 'utf8', function(err,data){
if(err){
reject(err)
}else{
resolve(data)
}
});
})
}
pReadFile('./data/a.txt').then(function(data){
console.log(data)
return pReadFile('./data/b.txt')
}).then(function(data){
console.log(data)
return pReadFile('./data/c.txt')
}).then(function(data){
console.log(data)
})
9.4 Promise和callback方式对比
callback
get('http://127.0.0.1:3000/users/4',function(userData){
get('http://127.0.0.1:3000/jobjs',function(jobsData){
var htmlStr = template('tpl', {
user: JSON.parse(userData),
jobs: JSON.parse(jobsData)
})
console.log(htmlStr)
document.querySelector('#user_form').innerHTML = htmlStr
})
})
promise
var data = {}
$.get('http://127.0.0.1:3000/users/4')
.then(function(user){
data.user = user
return $.get('http://127.0.0.1:3000/jobjs')
})
.then(function(jobs){
data.jobs = jobs
var htmlStr = template('tpl', data)
document.querySelector('#user_form').innerHTML = htmlStr
})