promise
Promise的状态
Promise对象有三个状态:
- 进行中(pending)
- 成功(resolved)
- 失败(rejected)
Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成');
resolve('数据');
}, 2000);
});
resolve用法
所以我们用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数
function runAsync(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('执行完成');
resolve(数据');
}, 2000);
});
return p;
}
runAsync()
在我们包装好的函数最后,会return出Promise对象,之后调用then方法,then里面可以传入两个函数,第一个就是关于resolve的函数
runAsync().then(function(data){
console.log(data);
//后面可以用传过来的数据做些其他操作
//......
});
reject的用法
reject的作用就是把Promise的状态置为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调
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);
}
);
- getNumber函数用来异步获取一个数字,2秒后执行完成,如果数字小于等于5,我们认为是“成功”了,调用resolve修改Promise的状态。否则我们认为是“失败”了,调用reject并传递一个参数,作为失败的原因.
- 运行getNumber并且在then中传了两个参数,前面说了then方法可以接受两个参数,第一个对应resolve的回调,第二个就是reject的回调
链式操作的用法
promise的诞生就是为了解决回调地狱,而链式操作就完美的解决了这点
function runAsync1(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务1执行完成');
resolve('数据1');
}, 1000);
});
return p;
}
function runAsync2(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务2执行完成');
resolve('数据2');
}, 2000);
});
return p;
}
function runAsync3(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务3执行完成');
resolve('数据3');
}, 2000);
});
return p;
}
runAsync1()
.then(function(data){
console.log(data);
return runAsync2();
})
.then(function(data){
console.log(data);
return '直接返回数据'; //这里直接返回数据
})
.then(function(data){
console.log(data);
});
输出的结果
- 异步任务1执行完成
- 数据1
- 异步任务1执行完成
- 数据1
- 直接返回数据'
catch的用法
Promise对象除了then方法,还有一个catch方法,它和then的第二个参数一样,用来指定reject的回调
getNumber()
.then(function(data){
console.log('resolved');
console.log(data);
})
.catch(function(reason){
console.log('rejected');
console.log(reason);
});
效果和写在then的第二个参数里面一样。不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。请看下面的代码:
getNumber()
.then(function(data){
console.log('resolved');
console.log(data);
console.log(somedata); //此处的somedata未定义
})
.catch(function(reason){
console.log('rejected');
console.log(reason);
});
在resolve的回调中,我们console.log(somedata);而somedata这个变量是没有被定义的。如果我们不用Promise,代码运行到这里就直接在控制台报错了 ,不往下运行了。但是在这里,因为有catch,它会把错误原因传到了reason参数中。即便是有错误的代码也不会报错了,这与我们的try/catch语句有相同的功能。
all的用法
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。我们仍旧使用上面定义好的runAsync1、runAsync2、runAsync3这三个函数
Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});
用Promise.all来执行,all接收一个数组参数,里面的值最终都算返回Promise对象。这样,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面all会把所有异步操作的结果放进一个数组中传给then,就是上面的results,输出结果
- 异步任务1执行完成
- 异步任务2执行完成
- 异步任务3执行完成
- [ '数据1' ,'数据2','数据3']
有了all,你就可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据
race的用法
race与all相反,谁先执行完成,谁就调用then
Promise
.race([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});
结果
- 异步任务1执行完成
- 数据1
- 异步任务2执行完成
- 异步任务3执行完成