七天搞定node.js---第五天

自学node.js第五天的笔记。

异步编程

setTimeout()是一个异步api

1
2
3
4
5
6
7
8
9
10
11
function f1() {
console.log(1)
setTimeout(function() {
console.log(2)
}, 2000)
console.log(3)
}
f1()


// 结果:1 3 2

不成立的情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function f1(x, y) {
var ret
console.log(1)
setTimeout(function() {
ret = x + y
console.log(2)
}, 2000)
console.log(3)
return ret
}
console.log(f1(10 + 20)) =>undefined

//输出结果:
// 1
// 3
// undefined
// 2

使用回调函数:

1
2
3
4
5
6
7
8
9
function f1(x, y, callback) {
setTimeout(function() {
var ret = x + y
callback(ret)
}, 2000)
}
f1(10, 10, function(ret) {
console.log(ret)
})

2秒后得到结果:20

封装ajax,理解回调函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>ajax</title>
</head>

<body>

</body>
<script>
function get(url, callback) {
var oReq = new XMLHttpRequest()
oReq.onload = function() {
callback(oReq.responseText)
}
oReq.open("get", url, true)
oReq.send()
}
get('data.json', function(data) {
console.log(data)
})
</script>

</html>

MongoDB

安装

启动和关闭数据表

启动:

1
2
3
4
// mongodb 默认使用执行 mongod 命令所处盘符根目录下的 /data/db 作为自己数据存储目录
// 所以在第一次执行该命令之前先自己手动新建一个 /data/db

mongod

如果想要修改默认的数据库存储目录,可以:

1
mongod --dbpath-数据库存储目录路径

停止:

1
在开启服务的控制台,直接 ctrl+c 就能停止。

连接和退出数据库

连接:

1
2
3
// 默认连接本机的 MongoDB 服务

mongo

退出:

1
exit

基本命令

  • show dbs
    • 查看显示所有数据库
  • db
    • 查看当前操作的数据库
  • use 数据库名称
    • 切换到指定的数据库(如果没有会新建)
  • 插入数据

mongoose

MongoDB 数据库的基本概念

  • 可以有多个数据库
  • 一个数据库中可以有多个集合(表)
  • 一个集合中可以有多个文档(表记录)
  • 文档结构很灵活,没有任何限制
  • MongoDB 非常灵活,不需要想 MySQL 一样先创建数据库、表、设计表结构
    • 当你需要插入数据的时候,只需要指定往哪个数据库的哪个集合操作就可以了
    • 一切都由 MongoDB 来帮你自动完成建库建表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
qq:{
users:[
{name:'木槿0',age:15},
{name:'木槿1',age:17},
{name:'木槿2',age:19}
],
products:[

],
......
},
taobao:{

},
baidu:{

}
}

起步

安装:

1
npm i mongoose

hello world:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var mongoose = require('mongoose');

// 连接 MongoDB 数据库
mongoose.connect('mongodb://localhost/test', { useMongoClient: true });

mongoose.Promise = global.Promise;

// 创建一个模型
// 就是在设计数据库
// MongoDB 是动态的,非常灵活,只需要在代码中设计你的数据库就可以了
// mongoose 这个包就可以让你的设计编写过程变的非常的简单
var Cat = mongoose.model('Cat', { name: String });

for (var i = 0; i < 100; i++) {
// 实例化一个 Cat
var kitty = new Cat({ name: '喵喵' + i });

// 持久化保存 kitty 实例
kitty.save(function(err) {
if (err) {
console.log(err);
} else {
console.log('meow');
}
});
}

官方指南

设计 Schema 发布 Model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
var mongoose = require('mongoose')

var Schema = mongoose.Schema
// 1. 连接数据库
// 指定连接的数据库不需要存在,当你插入第一条数据之后就会自动被创建出来
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
// 第一个参数:传入一个大写名词单数字符串用来表示你的数据库名称
// mongoose 会自动将大写名词的字符串生成小写复数的集合名词
// 例如这里的 User 最终会变为 users 集合名称
// 第二个参数:架构 Schema
// 返回对象:模型构造函数
var User = mongoose.model('User', userSchema)



// 4.当我们有了模型构造函数之后,就可以使用这个构造函数对 users 集合中的数据为所欲为了(增删改查)

增加数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
var mongoose = require('mongoose')

var Schema = mongoose.Schema
// 1. 连接数据库
// 指定连接的数据库不需要存在,当你插入第一条数据之后就会自动被创建出来
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
// 第一个参数:传入一个大写名词单数字符串用来表示你的数据库名称
// mongoose 会自动将大写名词的字符串生成小写复数的集合名词
// 例如这里的 User 最终会变为 users 集合名称
// 第二个参数:架构 Schema
// 返回对象:模型构造函数
var User = mongoose.model('User', userSchema)



// 4.当我们有了模型构造函数之后,就可以使用这个构造函数对 users 集合中的数据为所欲为了(增删改查)
var admin = new User({
username: 'admin',
password: '123456',
email: 'xq-ambition@qq.com'
})

admin.save(function(err, ret) {
if (err) {
console.log('保存失败~')
} else {
console.log('保存成功')
console.log(ret)
}
})

查询数据

查询所有:

1
2
3
4
5
6
7
User.find(function(err, ret) {
if (err) {
console.log('查询失败~')
} else {
console.log(ret)
}
})

按条件查询所有:

1
2
3
4
5
6
7
8
9
User.find({
username: '莫子谦' //条件
}, function(err, ret) {
if (err) {
console.log('查询失败~')
} else {
console.log(ret)
}
})

按条件查询单个:

1
2
3
4
5
6
7
8
9
10
User.findOne({ // 查询符合条件的一个
username: '莫子谦', //条件
password: 'xuqian'
}, function(err, ret) {
if (err) {
console.log('查询失败~')
} else {
console.log(ret)
}
})

删除数据

根据条件删除所有:

1
2
3
4
5
6
7
8
9
10
User.remove({
username: '莫子谦' //删除条件
}, function(err, ret) {
if (err) {
console.log('删除失败~')
} else {
console.log('删除成功')
console.log(ret)
}
})

根据条件删除一个:

1
Model.findOneAndRemove(conditions,[options],[callback])

根据 ID 删除一个

1
Model.findByIdAndRemove(id,[options],[callback])

更新数据

根据条件更新所有:

1
Model.update(conditions,doc,[options],[callback])

根据指定条件更新一个:

1
Model.findOneAndUpdate(conditions,[updata],[opyions],[callback])

根据 ID 更新一个:

1
2
3
4
5
6
7
8
9
10
User.findByIdAndUpdate('5d83539e2167524ff85cae99', { //需要更改数据的id
//需要更新的内容
password: '9090909'
}, function(err, ret) {
if (err) {
console.log('更新数据失败~')
} else {
console.log('更新数据成功')
}
})

使用 node 操作 MySQL 数据库

安装:

1
npm install mysql

整体感知:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var mysql = require('mysql');
// 1.创建连接
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'users'
});

// 2.连接数据库
connection.connect();

//3.执行数据库操作
connection.query('SELECT * FROM `students`', function(error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results);
});

// connection.query('INSERT INTO students VALUES(null,"admin","123456")', function(error, results, fields) {
// if (error) throw error;
// console.log('The solution is: ', results);
// });

//4. 关闭连接
connection.end();

Promise

callback hell:

回调地狱

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var fs = require('fs')

fs.readFile('./data/a.txt', 'utf8', function(err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)

})
fs.readFile('./data/b.txt', 'utf8', function(err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)

})
fs.readFile('./data/c.txt', 'utf8', function(err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
})

不一定谁先谁后,同等文件大小取决于计算机的调度机制,文件越大读取越慢。

所以通过回调嵌套的方式来保证执行顺序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var fs = require('fs')

fs.readFile('./data/a.txt', 'utf8', function(err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
fs.readFile('./data/b.txt', 'utf8', function(err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
fs.readFile('./data/c.txt', 'utf8', function(err, data) {
if (err) {
// return console.log('读取失败')
// 抛出异常
// 1. 阻止程序的执行
// 2. 把错误消息打印到控制台
throw err
}
console.log(data)
})
})
})

为了解决多次嵌套,最终难以维护的问题,在 EcmaScript6 中新增了一个 API:Promise

Promise
参考文档:http://es6.ruanyifeng.com/#docs/promise

Promise 基本语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var fs = require('fs')
// Promise 是一个构造函数


// 使用:

// 1.创建 Promise 容器,给别人一个承诺。

// Promise 容器一旦被创建,就开始执行里面的代码。

var p1 = new Promise(function(resolve, reject) {
fs.readFile('./data/a.txt', 'utf8', function(err, data) {
if (err) {
// console.log(err)
reject(err)
} else {
// console.log(data)
resolve(data)
}
})
})

// then 方法接收的 function 就是容器中的 resolve 函数

p1.then(function(data) {
console.log(data)
}, function(err) {
console.log('读取文件失败~', err)
})

Promise 解决回调地狱 嵌套问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
var fs = require('fs')
// Promise 是一个构造函数


// 使用:

// 1.创建 Promise 容器,给别人一个承诺。

// Promise 容器一旦被创建,就开始执行里面的代码。

var p1 = new Promise(function(resolve, reject) {
fs.readFile('./data/a.txt', 'utf8', function(err, data) {
if (err) {
// console.log(err)
reject(err)
} else {
// console.log(data)
resolve(data)
}
})
})

var p2 = new Promise(function(resolve, reject) {
fs.readFile('./data/b.txt', 'utf8', function(err, data) {
if (err) {
// console.log(err)
reject(err)
} else {
// console.log(data)
resolve(data)
}
})
})

var p3 = new Promise(function(resolve, reject) {
fs.readFile('./data/c.txt', 'utf8', function(err, data) {
if (err) {
// console.log(err)
reject(err)
} else {
// console.log(data)
resolve(data)
}
})
})

// then 方法接收的 function 就是容器中的 resolve 函数

p1.then(function(data) {
console.log(data)
return p2
}, function(err) {
console.log('读取文件失败~', err)
}).then(function(data) {
console.log(data)
return p3
}, function(err) {
console.log('读取文件失败~', err)
}).then(function(data) {
console.log(data)
}, function(err) {
console.log('读取文件失败~', err)
})

封装 Promise-api (readFile)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var fs = require('fs')

function pReadFile(filePath) {
return new Promise(function(resolve, reject) {
fs.readFile(filePath, 'utf8', function(err, data) {
if (err) {
// console.log(err)
reject(err)
} else {
// console.log(data)
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)
})

Promise使用场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>promise应用</title>
</head>

<body>
<form action="00-callback.js" method="get" id="user_form">
</form>
<script type="text/template" id="tpl">
<div>
<label for="">用户名</label>
<input type="text" value="{{user.username}}">
</div>

<div>
<label for="">年龄</label>
<input type="text" value="{{user.age}}">
</div>
<div>
<label for="">用户名</label>
<select name="" id="">
{{each jobs}}
{{if user.job === $value.id}}
<option value="{{$value.id}}" selected>{{$value.name}}</option>
{{else}}
<option value="{{$value.id}}">{{$value.name}}</option>
{{/if}}
{{/each}}
</select>
</div>

</script>
</body>

<script src="./node_modules/art-template/lib/template-web.js"></script>
<script src="./node_modules/jquery/dist/jquery.min.js"></script>
<script>
// 嵌套写法
// get('http://localhost:3000/users/4', function(userData) {
// get('http://localhost:3000/jobs', function(jobsData) {
// // console.log(userData, jobsData)
// var htmlStr = template('tpl', {
// user: JSON.parse(userData),
// jobs: JSON.parse(jobsData)
// })
// // console.log(htmlStr)
// document.querySelector('#user_form').innerHTML = htmlStr
// })

// })

var data = {}
$.get('http://localhost:3000/users/4')
.then(function(userData) {
data.user = userData
return $.get('http://localhost:3000/jobs')
})
.then(function(jobsData) {
data.jobs = jobsData
// console.log(data)
var htmlStr = template('tpl', data)
document.querySelector('#user_form').innerHTML = htmlStr
})

function get(url, callback) {
var oReq = new XMLHttpRequest()
oReq.onload = function() {
callback(oReq.responseText)
}
oReq.open("get", url, true)
oReq.send()
}
</script>

</html>

源代码可以去我的 github 克隆

-------------本文结束感谢您的阅读-------------
木槿前端不求人,有空就来坐坐。
0%