Promise

作者 新城 日期 2017-09-11
Promise
  • Promise对象
  • then方法
  • catch方法
  • 静态方法(resolve,reject,all,race)

Promise对象参考

resolve

参数 resolve reject 都是回调函数
resolve 异步操作执行成功以后回调函数
reject 异步操作执行失败以后回调函数

1
2
3
4
5
6
7
8
9
10
11
function runAsync(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成');
resolve('随便什么数据');
}, 2000);
});
return p;
}
runAsync()

一旦调用构造函数开始生成Promise对象(如上面myPromise),就会立即执行异步操作
注意!我只是new了一个对象,并没有调用它,我们传进去的函数就已经执行了。所以我们用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数

1
2
3
4
5
runAsync().then(function(data){
console.log(data);
//后面可以用传过来的数据做些其他操作
//......
})

输出:‘执行完成’‘随便什么数据’
在runAsync()的返回上直接调用then方法,then接收一个参数,是函数,并且会拿到我们在runAsync中调用resolve时传的的参数

then里面的函数就跟我们平时的回调函数一个意思

不用Promise实现上述功能

1
2
3
4
5
6
7
8
9
10
function runAsync(callback){
setTimeout(function(){
console.log('执行完成');
callback('随便什么数据');
}, 2000);
}

runAsync(function(data){
console.log(data);
});

Promise优势
多层回调函数的时候 then方法可以一层一层连续传递

链式操作的用法

1
2
3
4
5
6
7
8
9
10
11
12
runAsync1()
.then(function(data){
console.log(data);
return runAsync2(); //返回函数并且执行
})
.then(function(data){
console.log(data);
return runAsync3(); //runAsync2返回结果 后续操作
})
.then(function(data){
console.log(data);
});

上诉 return 也可以直接返回数据并不是返回函数

reject的用法

reject就是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
26
27
function getNumber(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num<=5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000);
});
return p;
}

getNumber()
.then(
function(data){
console.log('resolved');
console.log(data);
},
function(reason, data){
console.log('rejected');
console.log(reason);
}
);

catch的用法

异常捕获 相当于代码在resolved中执行出错的话 会执行catch 或者代替执行rejected

1
2
3
4
5
6
7
8
9
10
getNumber()
.then(function(data){
console.log('resolved');
console.log(data);
console.log(somedata); //此处的somedata未定义
})
.catch(function(reason){
console.log('rejected');
console.log(reason);
});

all方法

Promise的all方法提供了并行执行异步操作的能力

1
2
3
4
5
Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});

all接收一个数组参数,里面的值最终都算返回Promise对象.这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面
返回的数据都在then里面呢,all会把所有异步操作的结果放进一个数组中传给then

1
2
3
4
5
Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});


//小结
打开网页时,预先加载需要用到的各种资源如图片、flash以及各种静态文件。所有的都加载完后,我们再进行页面的初始化。

race的用法

all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是race方法

应用场景
比如我们可以用race给某个异步请求设置超时时间,并且在超时后执行相应的操作,代码如下:

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
function requestImg(){
var p = new Promise(function(resolve, reject){
var img = new Image();
img.onload = function(){
resolve(img);
}
img.src = 'xxxxxx';
});
return p;
}

function timeout(){
var p = new Promise(function(resolve, reject){
setTimeout(function(){
reject('图片请求超时');
}, 5000);
});
return p;
}

Promise
.race([requestImg(), timeout()])
.then(function(results){
console.log(results);
})
.catch(function(reason){
console.log(reason);
});