回调函数callback,Promise
# 回调函数callback
函数也是一种数据类型,既可以当做参数进行传递,也可以当作方法的返回值。
回调函数并不是函数自调用,而是将函数作为参数。一般情况下,把函数作为参数的目的就是为了获取函数内部的异步操作结果。异步是因为js是单线程的,对一些耗时的异步操作放在后面执行可提高性能。
异步操作:
- setTimeout
- readFile
- writeFile
- readdir
- ajax
往往异步API都伴随一个回调函数。
function add(x, y, callback) {
setTimeout(function () {
var ret = x + y
callback(ret)
})
}
add(10, 20, function (ret) {
console.log(ret)//使用回调函数是为了方便拿到异步操作结果,并做一些其他操作
})
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# Promise
callback hell:回调地狱,保证了异步操作的执行顺序,但嵌套太深,难以维护。
Promise使用场景:同一个地方需要请求多个接口的数据,此时请求操作都要同步,方便拿到所有数据进行处理。
为了解决回调地狱嵌套
问题,所以在ES6中新增了一个API:Promise
。
- Promise是一个构造函数,它本身不是异步,但内部往往都是封装一个异步任务
- Promise容器一旦创建,就开始执行里面的代码
console.log(1)
//创建Promise容器,容器里面放的是异步任务
var p1 = new Promise(function (resolve, reject) {//参数1:解决,参数2:失败
console.log(2)
fs.readFile('./a.txt', 'utf8', function (err, data) {//异步任务
if (err) {
//操作失败了
reject(err)//调用了then方法的第二个参数函数
} else {
//操作成功了
console.log(3)
resolve(data)//调用了then方法的第一个参数函数
}
})
})
console.log(4)//执行顺序是1 2 4 3,虽然Promise会立即执行,但当发现里面是异步操作,又往下先执行了
//当p1成功了,就执行then中指定的操作
p1.then(function (data) {//这里的function就是resolve
console.log(data)
}, function (err) {//这里的function指的是reject
console.log('读取文件失败了', err)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Promise嵌套调用
var p1 = new Promise(function (resolve, reject) {
fs.readFile('./a.txt', 'utf8', function (err, data) {//异步任务
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
var p2 = new Promise(function (resolve, reject) {
fs.readFile('./b.txt', 'utf8', function (err, data) {//异步任务
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
var p3 = new Promise(function (resolve, reject) {
fs.readFile('./c.txt', 'utf8', function (err, data) {//异步任务
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
//then的链式调用
p1.then(function (data) {//这里的function就是resolve
console.log(data)
//当p1读取成功时
return p2 //return了一个Promise对象,接着后面就是p2.then()
}, function (err) {//这里的function指的是reject
console.log('读取文件失败了', err)
})
.then(function (data) {//这里指的是p2的resolve
console.log(data)
return p3
})
.then(function (data) {
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
33
34
35
36
37
38
39
40
41
42
43
44
45
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
# 封装Promise版本的readFile
function pReadFile(filePath) {
return new Promise(function (resolve, reject) {
fs.readFile(filePath, 'utf8', function (err, data) {//异步任务
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
}
pReadFile('./a.txt')
.then(function (data) {
console.log(data)
return pReadFile('./b.txt')
})
.then(function (data) {
console.log(data)
return pReadFile('./c.txt')
})
.then(function (data) {
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24