什么是Promise
Promise对象用于表示一个异步操作的最终状态(完成或失败)以及其返回的值
- 同步任务会阻塞程序执行(alert、for、…)
- 异步任务不会阻塞程序执行(setTimeout、fs.readFiles)
特点: - 对象的状态不受外界影响‘
- 一旦状态改变就不会再变,任何时候都是这种结果.
回调函数与Promise
- 回调函数实现元素平移
function moveTo(el, x, y, cb) {
el.style.transform = `translate(${x}px,${y}px)`;
setTimeout(function() {
cb && cb();
}, 1000)
}
let el = document.querySelector('div');
let bu = document.querySelector('button');
bu.addEventListener('click', function() {
moveTo(el, 100, 200, function() {
moveTo(el, 200, 100, function() {
moveTo(el, 20, 40, function() {
moveTo(el, 0, 0, function() {
console.log('移动结束');
})
})
})
})
})
- Promise实现
function moveTo(el, x, y) {
return new Promise(resovle => {
el.style.transform = `translate(${x}px,${y}px)`;
setTimeout(function() {
resovle();
}, 1000)
})
}
let el = document.querySelector('div');
let bu = document.querySelector('button');
bu.addEventListener('click', function() {
moveTo(el, 100, 200).then(function() {
console.log("第一次移动");
return moveTo(el,20,30)
.then(function(){
console.log("第二次移动")
});
})
})
信任处理
- 普通的回调函数可能出现回调地狱问题,你无法预知它要执行几次,
- 但是Promise对象中的状态一旦被确定为成功或者失败,就不能被修改
执行一次
。 - Promise解决了1.第三方库的信任问题 2.回调地狱问题。
错误处理
注意点:Promise中的 then是异步处理
- then接受resolve 和 reject两参数来处理错误
function fn(val){
return new Promise((resolve,reject)=>{
if(val){
resolve({name:'dxy',age:18},{name:'hhh'}); //注意只能拿到一个对象
}else{
reject('404');
}
})
}
fn(true)
.then((res)=>{
console.log(res);
},(error)=>{
console.log(error);
})
- 实例的catch方法来捕获错误
fn(true)
.then((res)=>{
console.log(res);
return fn(false)
})
.then(()=>{
console.log("我不会被输出");
})
.catch(error=>{
console.log(error);
})
//注意:无法捕获最后一个catch中有无错误
- 无论成功还是是被,finally方法中的内容都会执行
fn(true)
.then(res=>{
console.log(res);
return fn(false);
})
.catch(error=>{
console.log(error);
return fn(false) //未对其做处理,所以会报错
})
.finally(()=>{
console.log(100); //无论成功或者失败,都会执行
})
- done( )方法,保证抛出任何可能出现的错误
因为Promise的内部错误不能冒泡到全局,为此提供了一种done方法,它总是处于回调链的尾端,保证抛出任何可能出现的错误
Promise.prototype.done=function(onFulfilled,onRejected){
this.then(onFulfilled,onRejected)
.catch(function(){
//抛出一个全局错误
setTimeout(()=>{throw reason},0);
})
}
Promise.all()
Promise.all方法用于将多个Promise实例包装成一个新的Promise 实例
let p=Promise.all([promise1,promise2]) //:Promise
注意点:
返回的每个成员都是Promise实例数组
- p的状态由promise1,promise2决定,只有两者的状态都变为fulfilled,p的状态才会变为fulfilled,此时promise1,promise2的返回值组成一个数组,传递给p的回调函数
- 只要promise1,promise2中一个被Rejected,p的状态就会变成Rejecte,此时第一个被Rejected的实例的返回值会传递给p的回调函数。
function getData1(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
console.log("我是第一条数据")
resolve('data1')
},1000)
})
}
function getData2(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
console.log("我是第二条数据")
resolve('data2')
},1000)
})
}
function getData3(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
console.log("我是第三条数据")
resolve('data3')
},1000)
})
}
function getData4(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
console.log("我是第四条数据")
resolve('data4')
},2000)
})
}
let p=Promise.all([getData1(),getData2(),getData3(),getData4()]);
p.then(arr=>{
console.log(arr);
})
- 注意点:若promise.all传参数组为空,
则直接返回成功
Promise.race()
注意点:
- 只要p1,p2,p3中实例率先改变状态,p的状态跟着改变,
率先改变状态的Promise实例返回值就传递给p的回调函数 - promise.race传参为空数组,就会
挂起
什么也不输出。
let p=Promise.all(p1,p2,p3]);
function getData1(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
console.log("我是第一条数据")
resolve('data1')
},1000)
})
}
function getData2(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
//console.log("我是第二条数据")
reject('data2 ere')
},500)
})
}
function getData3(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
console.log("我是第三条数据")
resolve('data3 ')
},1000)
})
}
let p=Promise.race([getData1(),getData2(),getData3()]);
p.then(arr=>{
console.log(arr);
},error=>{
console.log(error);
})
Promise.resolve &Promise.reject
Promise.resolve
有时需要将现有的对象转为Promise对象,Promise.resolve方法就起到这个作用
其参数传递分为以下四种情况:
- 参数是一个Promise实例
let p=new Promise(resolve=>{
resolve("hi");
})
let p2=Promise.resolve(p);
p2.then(data=>{
console.log(data);
})
- 参数是一个thenable对象
let thenable={
then:function(resolve,reject)=>{
resolve(23);
}
}
let p1=Promise.resolve(thenable);
p1.then(data=>{
console.log(data);//23
})
- 参数根本不是对象
如果参数是个原始值,那么Promise.resolve方法返回一个新的Promise对象,状态为Resolved
let p=Promise.resolve("dxy");
p.then(res=>{
console.log(res);//dxy
})
- 不带任何参数
直接返回一个Resolved状态的Promise对象
注意点:promise为微任务在本轮时间循环结束时执行,而不是在下一轮时间循环开始时
Promise.reject()
Promise.reject(reason)方法会返回一个新的Promise实例,状态为Rejected。
let p=Promise.reject('error');
//等同于
let p=new Promise((resolve.reject)=>reject('error'));