https://hzzly.github.io/2017/03/25/%E6%B5%85%E8%B0%88Promise/接触过promise的的都知道它的应用场景和用途,Promise可以用来避免异步操作函数里的嵌套回调(callback hell)问题,因为解决异步最直接的方法是回调嵌套,将后一个的操作放在前一个操作的异步回调里,但如果操作多了,就会有很多层的嵌套(回调地狱)。
1
2
3
4
5
6
7
8
9
10
|
$.ajax(url1,
function(data1){
$.ajax(url2,
function(data2){
$.ajax(url3,
function(data3){
done(data3);
})
});
});
|
Promise学术点的描述:
promise代表一个异步操作的执行返回状态,这个执行返回状态在promise对象创建时未必已知。它允许你为异步操作的成功或失败指定处理方法。
这使得异步方法可以像同步方法那样返回值:异步方法会返回一个包含了原返回状态的 promise 对象来替代原返回状态。
Promise的表现
如果使用回调方法处理多个操作的异步场景,判断某个操作成功或失败的控制在于声明的匿名函数里面,使用Promise对象则可以重新定义异步执行的状态和控制逻辑。
promises的最重要的特点就是它把我们处理任何函数调用的成功或者失败的方式规范成了可预测的形式,特别是如果这个调用实际上的异步的。
Promise中有几个状态:
- pending: 初始状态。 非 fulfilled 或 rejected。
- resolved: 成功的操作。也有的成为fulfilled 。
- rejected: 失败的操作。
状态转换关系为:
pending->resolved(fulfilled),pending->rejected。
用法
说了这么多,直接上代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
var promise =
new
Promise(
(resolve, reject) => {
if (success){
return resolve(res);
}
else {
return reject(err);
}
});
promise.then(
res => {
console.log(res);
}, err => {
})
|
或封装成方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
function fetch(data) {
return
new
Promise(
(resolve, reject) => {
if (success){
resolve(res);
}
else {
reject(err);
}
})
}
fetch(data)
.then(
res => {
console.log(res)
}, 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
25
26
27
|
function loadAsync1(){
return
new
Promise(
(resolve, reject) => {
setTimeout(
() => {
console.log(
'异步任务1');
resolve(
'异步任务1传过来的值');
},
2000);
});
}
function loadAsync2(data1){
return
new
Promise(
(resolve, reject) => {
setTimeout(
() => {
console.log(
'异步任务2');
resolve(
'异步任务2传过来的值');
},
2000);
});
}
function loadAsync3(data2){
return
new
Promise(
(resolve, reject) => {
setTimeout(
() => {
console.log(
'异步任务3');
resolve(
'异步任务3传过来的值');
},
2000);
});
}
|
有返回值
1
2
3
4
5
6
7
8
|
loadAsync1()
.then(
data1 => {
return loadAsync2(data1)
})
.then(
data2 => {
return loadAsync3(data2)
})
.then(okFn, failFn)
|
没有返回值
1
2
3
4
5
6
7
8
|
loadAsync1()
.then(data1 => {
loadAsync2(data1)
})
.then(data2 =>{
loadAsync3(data2)
})
.then(res => console.log(res))
|
输出的值为:
异步任务1
异步任务1传过来的值
异步任务2
异步任务2传过来的值
异步任务3
异步任务3传过来的值
promise.all方法
Promise.all 可以接收一个元素为 Promise 对象的数组作为参数,当这个数组里面所有的 Promise 对象都变为 resolve 时,该方法才会返回。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
var p1 =
new
Promise(
(resolve) => {
setTimeout(
() => {
resolve(
"第一个promise");
},
3000);
});
var p2 =
new
Promise(
(resolve) => {
setTimeout(
() => {
resolve(
"第二个promise");
},
1000);
});
Promise.all([p1, p2])
.then(
(result) => {
console.log(result);
});
|
上面的代码中,all接收一个数组作为参数,p1,p2是并行执行的,等两个都执行完了,才会进入到then,all会把所有的结果放到一个数组中返回,所以我们打印出我们的结果为一个数组。
值得注意的是,虽然p2的执行顺序比p1快,但是all会按照参数里面的数组顺序来返回结果。all的使用场景类似于,玩游戏的时候,需要提前将游戏需要的资源提前准备好,才进行页面的初始化。
之后会有express操作mongondb的基于Promise的封装,敬请期待!