一、为什么会出现Promise
JS是单线程运行的,就是说一次只能完成一个任务,如果有多个任务必须排队依次完成,没有Promise的时候,我们完成一个卖商品的任务:
需要层层回调函数
function sell(kehu,callback){
console.log(`紫紫接受客户${kehu}的产品询问`);
setTimeout(()=>{
// 卖出东西的概率为 0.2
if(Math.random() < 0.2){
//回调函数
callback(true)
}else(
//回调函数
callback(false)
)
},1000)
}
//调用函数
sell('小明',function(result){
if(result){
console.log(`商品种类较少,去别家看看`)
}else{
console.log(`颜色不太喜欢`)
sell('芳芳',function(result){
if(result){
console.log(`商品种类较少,去别家看看`)
}else{
console.log(`颜色不太喜欢`);
sell('小王',function(result){
if(result){
console.log(`商品种类较少,去别家看看`)
}else{
console.log(`颜色不太喜欢`)
}
})
}
})
}
})
})
这只是一个小任务,还没有多大问题,可是代码量不算少了;
所以promise出来了
二、什么是promise
利用 promise可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,promise对象提供统一的接口,似的控制异步操作更加容易。
但注意promise无法取消,一旦建立就会立即执行,无法中途取消。而且,如果不设置回调函数,promise内部抛出的错误不会反映到外部。当处于Pending状态时,无法得知进展到哪一个阶段。
promise有三个状态:
- Pending-promise的初始状态,等到任务完成或是被拒绝
- Resolved-执行完成并且成功的状态;
- Rejected-执行完成并且失败的状态。此三个状态不能相互逆转。
promise对象必须实现then方法,可以说then是promise的核心,而且then方法必须返回一个promise对象,同一个promise对象可以注册多个then方法,并且回调的执行顺序和他们注册的顺序一致。
then方法接收两个回调函数,他们分别是成功时的回调和失败时的回调。
三、Promise的用法
let p = new Promise((resolve, reject) => {
//做一些异步操作
setTimeout(() => {
console.log('执行完成');
resolve('我是成功!!');
}, 2000);
});
then 链式操作的用法
Promise的使用比callback函数调用简单、灵活的多:
p.then((data) => {
console.log(data);
})
.then((data) => {
console.log(data);
})
.then((data) => {
console.log(data);
});
reject的用法:
把Promise的状态置为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调
let p = new Promise((resolve, reject) => {
//做一些异步操作
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num<=5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000);
});
p.then((data) => {
console.log('resolved',data);
},(err) => {
console.log('rejected',err);
}
);
then中传了两个参数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。所以我们能够分别拿到他们传过来的数据。
catch 的用法
我们知道Promise对象除了then方法,还有一个catch方法,它是做什么用的呢?其实它和then的第二个参数一样,用来指定reject的回调。用法是这样:
p.then((data) => {
console.log('resolved',data);
}).catch((err) => {
console.log('rejected',err);
}
果和写在then的第二个参数里面一样。不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中
p.then((data) => {
console.log('resolved',data);
console.log(somedata); //此处的somedata未定义
})
.catch((err) => {
console.log('rejected',err);
});
在resolve的回调中,我们console.log(somedata);而somedata这个变量是没有被定义的。如果我们不用Promise,代码运行到这里就直接在控制台报错了,不往下运行了。