如何在Node中使用Promise
Updated:
一、回调地狱的产生
例如下面一段代码,分别访问三个文件,因为都是异步操作,所以无法保证执行结果的顺序]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var fs = require('fs')
fs.readFile('./data/a.txt', 'utf8', function (err, data) {
if (err) {
throw err
}
var fs = require('fs')
fs.readFile('./data/b.txt', 'utf8', function (err, data) {
if (err) {
throw err
}
var fs = require('fs')
fs.readFile('./data/c.txt', 'utf8', function (err, data) {
if (err) {
throw err
}
如何解决保证执行结果的顺序?
可以使用回调函数进行嵌套1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var fs = require('fs')
fs.readFile('./data/a.txt', 'utf8', function (err, data) {
if (err) {
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)
})
})
})
如果嵌套的次数太多就会产生回调地狱
二、Promise基本语法
为了解决以上编码方式带来的回调地狱嵌套,所以在ES6中新增了一个API:promise(一个构造函数)
promise是一个容器,容器中存放了一个异步任务,promise本身不是异步,但是内部封装了一个异步任务— pending,pending的结果只能变为两种:
- Resolved: 被解决的(成功)
- Rejected:被拒绝的 (失败)
1. 创建Promise容器
promise 容器一旦被创建就会执行里面的代码。
我创建了一个data目录下的a.txt文件,使用promise访问里面的数据1
2
3
4
5
6
7
8
9
10
11
12
var fs = require('fs')
new Promise(function(){
fs.readFile('./data/a.txt', 'utf8', function(err, data){
if(err){
console.log(err)
}else{
console.log(data)
}
})
})
但是其实,promisse的访问是异步操作,如下所示:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var fs = require('fs')
console.log(1)
new Promise(function(){
console.log(2)
fs.readFile('./data/a.txt', 'utf8', function(err, data){
if(err){
console.log(err)
}else{
console.log(3)
console.log(data)
}
})
})
console.log(4)
2. 如何获取成功和失败的数据
使用promise实例对象的then方法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 fs = require('fs')
var p1 = new Promise(function (resolve, reject) {
fs.readFile('./data/a.txt', 'utf8', function (err, data) {//异步任务
if (err) {
//失败调用
//调用的reject就相当于调用then方法的第二个参数-function err
reject(err)
} else {
//成功调用
//调用的resolve方法实际上就是then方法传递的那个function data
resolve(data)
}
})
})
p1
.then(function (data) {
console.log(data)
}, function (err) {
console.log('读取文件失败了', err)
})
3. 解决嵌套问题
当 p1 读取成功的时候,当前函数中 return 的结果就可以在后面的 then 中 function 接收到
当你 return 123 后面就接收到 123
return ‘hello’ 后面就接收到 ‘hello’
没有 return 后面收到的就是 undefined
我们可以 return 一个 Promise 对象
当 return 一个 Promise 对象的时候,后续的 then 中的 方法的第一个参数会作为 p2 的 resolve1
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
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)
return p2
}, function (err) {
console.log('读取文件失败了', err)
})
.then(function (data) {//该方法作为p2的resolve
console.log(data)
return p3
})
.then(function (data) {//该方法作为p3的resolve
console.log(data)
console.log('end')
})
结果输出三个文件中的数据,同时读取的顺序不会错
4. 封装Promise版本的readFile
1 |
|