开发很多的时候需要异步操作,常用的做法就是用回调函数,假如需要一连串的调用,并且后面一个调用依赖前一个返回的结果的时候,就得多层嵌套回调函数,比如下面这种情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
$('.animateEle').animate({
opacity:'.5'
}, 4000,function(){ //回调
$('.animateEle2').animate({
width:'100px'
},2000,function(){ //回调
$('.animateEle3').animate({
height:'0'
},1000,function(){
.......太乱
});
});
});

回调函数嵌入太多了,看晕了都,代码很不美观,于是es6加入了新特性解决这个问题,Promise.

Promise最大的好处就是可以链式的调用函数,起到异步回调函数的作用,看起来更加直观简洁,

resolve 和 reject

这是Promis最重要的两个方法,resolve方法可以让Promise对象的状态变为成功,reject是失败,举个例子一目了然:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function print (ready) {
return new Promise ((resolve, reject)=>{
if(ready){
resolve("Hello World!");
}else{
reject("Good bye!");
}
})
}
print(true).then(message=>{
alert(message);
},error=>{
alert(error);
}
);

then

Promise通常配合then方法来链式的使用,then方法里面第一个回调函数表示成功状态,也就是resolve,第二个是失败状态-reject,如果默认写一个参数的话,默认resolve

代码会输出 Hello World!

一个看不出来,多几个依赖状态就看着明显了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Print (ready) {
return new Promise ((resolve,reject)=>{
if(ready){
resolve("Hello World!");
}else{
reject("Good bye!");
}
});
}
function print1 () {
alert("World");
}
function print2 () {
alert("!");
}
Print(true)
.then(message=>{alert(message);})
.then(print1)
.then(print2)

上面的代码依次等到上一个Promise对象返回成功后依次调用,否则按照老式的写法还得包进回调函数里,包好几层就很不方便容易看晕,这样链式的调用取代老式写法,这是Promise最常用的。

catch:

当返回发生错误的时候,会触发catch,可以写成then(fn).catch(fn),相当于 then(fn).then(null, fn);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function Print (ready) {
return new Promise ((resolve,reject)=>{
if(ready){
resolve("Hello World!");
}else{
reject("Good bye!");
}
});
}
function print1 () {
alert("World");
}
function print2 () {
alert("!");
}
    function catch_error () {
      alert('error');
    }
Print(false)
.then(message=>{alert(message);})
.then(print1)
.then(print2)
       .catch(catch_error)

失败的状态其实可以写进then的第二个参数里,但是一般不用那么些,用catch捕获更符合promise的初衷

all:

Promise.all 可以接收一个元素为 Promise 对象的数组作为参数,当这个数组里面所有的 Promise 对象都变为 resolve 时,该方法才会返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var p1 = new Promise(resolve=>{
setTimeout(()=>{
resolve("Hello");
},3000);
});
var p2 = new Promise(resolve=>{
setTimeout(()=>{
resolve("World");
},1000);
});
Promise.all([p1, p2]).then(result=>{
console.log(result);
});

还有一个和 Promise.all 相类似的方法 Promise.race,它同样接收一个数组,不同的是只要该数组中的 Promise 对象的状态发生变化(无论是 resolve 还是 reject)该方法都会返回。

es6的Promise还有一些方法,就不写了,以上是常用的.

es7里还有async函数,也起到异步作用,就不多说了先.

兼容性不是很好,vue开发的时候常常会用babel转码,要么使用jquery的Deferred对象,用法跟Promise差不多。象,用法跟Promise差不多。