不废话,上来就整,先看一下写法,new了个构造函数,传了两个匿名函数参数resolve,reject,分别是成功和失败,需要注意的一点就是new完之后就开始执行,很果断,不带犹豫的,这就是promise的脾气啊
{
let p=new Promise((resolve,reject)=>{
setTimeout(
()=>{
console.log('2');
resolve('success');
},0);
}).then((res)=>{
console.log(res+1);
return 3;
}).then((res)=>{
console.log(res);//3
});
}
下面来一段img加载的代码,由于promise脾气太过于耿直,so,咱们把他扔到function里,把他return出去,这样就可以随时随用了,再也不用担心promise的脾气了,这段代码里加了一个then,then是什么鸟呢,他是promise上面一个方法,传两个匿名函数,一个成功,一个失败,在promise的resolve里面传的参数就会传到then的成功函数里,同样的reject也是
{
function loadImg(url){
const p=new Promise((resolve,reject)=>{
let img=new Image();
img.onload=function (){
resolve('加载成功');
console.log('success');
};
img.onerror=function (){
reject('加载失败');
console.log('error');
};
img.src=url;
console.log(url);
});
return p;
}
//加载图片
loadImg('http://imgsrc.baidu.com/imgad/pic/item/
267f9e2f07082838b5168c32b299a9014c08f1f9.jpg').then((suc)=>{
console.log(suc)
return loadImg('http://imgsrc.baidu.com/');
//成功
},(err)=>{
console.log(err);
//失败
}).then(suc=>{
console.log(suc);
alert(suc);
},err=>{
console.log(err);
alert(err);
});
//上面就是resolve方法使用,当然reject也是这种用法,
then真是犀利的 一B啊
}
-
Promise.resolve方法可以将不是promise的对象转化为promise对象
//例如
Promise.resolve(1)
//相当于
new Promise(resolve=>resolve(1));
可以传4种类型的参数
- 不传参数
Promise.resolve().then(()=>{ //执行code });
- 传promise的实例 将实例的结果原封不动的返回出去
Promise.resolve(new Promise((resolve,reject)=>{reject(2)})).catch(err=>{ console.log(err);//2 });
- 传一个带有then方法的对象,那么会先执行then的方法,并且这个方法里必须执行resolve或者reject方法,来改变状态,不然不会执行下去
// 如果本地有数据就不请求,没有就请求 let data=""; let thenable={ then(resolve,reject){ setTimeout(()=>{ resolve(14); },1000); } } let p=data?Promise.resolve(data):Promise.resolve(thenable) p.then(res=>{ console.log(res) });
- 除去上面三种情况的其他值
Promise.resolve("4").then(res=>{ console.log(res); })
-
Promise.reject方法也会返回一个新的 Promise 实例,该实例的状态为rejected
//传一个promise实例
Promise.reject(new Promise((resolve,reject)=>{reject(42)})).catch(res=>{
res.catch(e=>{
console.log(e);//42
})
});
//传一个字符串
Promise.reject("哈哈").catch(err=>{
console.log(err);//哈哈
});
通过上面例子可以看出Promise.reject
无论传什么参数,都会原封不动地作为reject的理由,变成后续方法的参数
-
look一下all的用法,感觉这特么的就是个大招啊,异步执行的,并且在所有异步操作执行完后才执行回调,谁拖大腿根听谁的
{
function getImg(url){
const p=new Promise((resolve,reject)=>{
let img=new Image();
img.src=url;
img.onload=function (){
resolve('suc');
};
img.onerror=function (){
reject('err');
};
});
return p;
}
function hideBanner(flag){
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{
if (flag){
resolve('隐藏成功');
}else{
reject('失败');
}
},1000);
console.log('隐藏图片');
});
return p;
}
Promise.all([getImg('http://imgsrc.baidu.com/imgad/pic/item/
267f9e2f07082838b5168c
32b299a9014c08f1f9.jpg'),hideBanner(true)]).then((results)=>{
console.log(results);//["suc", "隐藏成功"]
});
//传的这个URL路径是错误的并不会加载成功,所以会走reject
Promise.all([getImg('http://imgsrc.baidu.com
/pic/item/267f9e2f07082838b51
68c32b8f1f9.jpg'),hideBanner(false)]).then((results)=>{
console.log(results);
}).catch(e=>{
console.log(e);//err
});
//promise真是个够义气的哥们啊,要么都成功,要么一个失败,就都失败
}
-
再see一下race的方法,这个也是异步的,但是跟all不同的是,谁跑的快听谁的,谁跑到终点就开始执行then了
{
function timeout1(){
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('我是1s就执行');
},1000);
});
return p;
}
function timeout2(){
let p=new Promise((resolve,relect)=>{
setTimeout(()=>{
console.log('console出来的==》我是2s就执行');
resolve('我是2s就执行');
},2000);
});
return p;
}
Promise.race([timeout1(),timeout2()]).then((results)=>{
console.log(results);//我是1s就执行
});
//很明显,timeout1先执行完,所以then就输出timeout1的成功参数,那么就别以为timeout2就不执行了,其实人家也执行着呢,只不过没有在then里体现出来,那就有人问了,这玩意有个鸟用啊,你还真说对了,这玩意还真有个鸟用,下面看一下请求图片的时候,或者请求借口的时候时间长了如果还没有成功,那就是成功的挂掉了,我们得给用户一个反馈
function getImg(url){
const p=new Promise((resolve,reject)=>{
let img=new Image();
img.src=url;
img.onload=function (){
resolve('suc');
};
img.onerror=function (){
console.log('gua');
//reject('err');
//注意这里,因为要在timeout上做失败处理,所以这里就不要执行reject了,因为一旦把状态变为rejected,那么就不会执行timeout了
};
});
return p;
}
function timeout(){
let p=new Promise((resolve,reject)=>{
setTimeout(()=>{
reject('诶哟~挂掉了');
},5000);
});
return p;
};
Promise.race([getImg('http://imgsrc.baidu.com/imgad/hehe'),timeout()]).then((result)=>{
console.log(result);
}).catch(e=>{
console.log(e);//诶哟~挂掉了
});
}
-
allSettled的方法
有时候我们需要一组异步的操作都结束了,无论其中的每一个是失败还是成功,再进行下一步的操作,就可以用allSettled
方法
const resolve=Promise.resolve(12);
const reject=Promise.reject(-1);
Promise.allSettled([resolve,reject]).then((res)=>{
console.log(res)
/*
[
{"status": "fulfilled","value": 12},
{"status": "rejected","reason": -1}
]
*/
})
allSettled
接受一个数组,执行完,他的状态只会是fulfilld
,所以只会执行then
的第一个匿名函数,执行完得到的结果是一个数组,分别是带有状态的json
,可以来区分执行完的状态失败和成功
/*
[
{"status": "fulfilled","value": 12},
{"status": "rejected","reason": -1}
]
*/
//过滤状态成功的结果
const fulfilledRes=res.filter(item=>item.status==="fulfilled");
//过滤状态失败的结果
const rejectRes=res.filter(item=>item.status==="reject");
-
any方法,接受一个数组参数,里面都是
promise
实例,最后返回一个promise
实例
any
方法和race
方法很像,但是race
是根据返回结果时间来执行的,而any是根据状态执行的,只要一组中其中一个的状态变为fulfilled
,那么any
的状态就会变成fulfilled
,或者一组中所有的成员都变成了reject
状态,那么any
也会变成reject
状态
const resolve=Promise.resolve(12);
const reject1=Promise.reject(-1);
const reject2=Promise.reject(-2);
const reject3=Promise.reject(-3);
//一个状态为`fulfilled`,那么`any`的状态就会是`fulfilled`
Promise.any([reject1,resolve]).then((res)=>{
console.log(res);//12
});
//所有的实例状态都是`reject`,`any`的状态也是`reject`
Promise.any([reject1,reject2,reject3]).catch((results)=>{
console.log(results);//AggregateError: All promises were rejected
console.log(results.errors);//[-1, -2, -3]
});
通过以上结果可以看出,如果参数一组实例都是reject
状态,那么返回的结果results
是无法直接显示结果的,需要用results.errors
才能显示出来返回的结果
-
再来讲一下catch的方法
//在上面的例子中可以看出,catch是可以顶替reject对应的匿名函数的,那么还有一个作用,是用来顶替try catch的,来看一下下面的例子
{
let p=new Promise((resolve,reject)=>{
reject('error');
show();//未定义这个show函数
}).then(res=>console.log(res)).catch(e=>{
console.log(e);//error
//下面还可以执行别的代码,如果不用catch的话,js报错就挂掉了,不往下执行了,并且过滤掉了show这个错误
console.log('继续执行代码');
});
}
{
let p=new Promise((resolve,reject)=>{
show();//未定义这个show函数
}).then(res=>console.log(res)).catch(e=>{
console.log(e);//show is not defined
//下面还可以执行别的代码,如果不用catch的话,js报错就挂掉了,不往下执行了,状态不是reject和resolve的话,不会过滤掉show这个错误
console.log('继续执行代码');
});
}
//在then里报错,还是会进到catch里面,不会影响代码继续执行
{
let p=new Promise((resolve,reject)=>{
resolve('success');
}).then(res=>{
console.log(res);
show();//未定义这个show函数
}).catch(e=>{
console.log(e);//show is not defined
//下面还可以执行别的代码,如果不用catch的话,js报错就挂掉了,不往下执行了
console.log('继续执行代码');
});
});
}
-
finally 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作
{
let p=new Promise((resolve,reject)=>{
resolve('success');
}).then(res=>{
console.log(res);
}).catch(e=>{
console.log(e);
}).finally(()=>{
//执行代码
});
});
finally
方法传一个回调函数,但是不接受任何参数,无论Promise
的状态到底是fulfilled
还是rejected
,执行完then
或者catch
之后都会执行finally
,所以与状态无关
finally
的实现很简单,其实就是又一次执行了then
的方法
class Promise{
finally=(cb)=>{
return this.then(
value=>this.resolve(cb()).then(()=>value)),
reason=>this.resolve(cb()).then(()=>reason)
}
}
从上面的实现还可以看到,finally
方法总是会返回原来的值。
// resolve 的值是 2
Promise.resolve(2).finally(() => {})
关于promise就介绍这么多,希望对你有所帮助,如果想看更详细的资料,请狠狠的点击我