promise 三种状态:pedding(进行中)、fulfilled(已成功)、rejected(已失败)。
特点:状态不受外界的影响, 一旦状态改变就不会再变(pending–>fulfilled,pending–>rejected)。
Promise是一个构造函数,用来生成promise实例。
Promise构造函数接受一个函数作为参数,这个函数有两个参数。
<script>
const p =new Promise(function(resolve,reject) {
//resolve函数:将Promise对象从未完成变成成功,再异步操作成功的时候调用
resolve()//返回异步操作的结果,结果作为参数传递
//reject函数:将Promise对象从未完成变成失败,再异步操作失败的时候调用
reject()//返回异步操作的结果,结果作为参数传递
})
</script>
Promise实例方法
- then():用于指定当 Promise 对象的状态从 “pending”(进行中)转变为 “fulfilled”(已成功)时应该执行的操作。
在实际使用中,.then() 方法通常只提供一个 onFulfilled 回调,而错误处理则通过链式调用 .catch() 方法来完成。但 .then() 方法也完全有能力处理错误,只需要你提供两个回调函数即可。
如果实例状态发生改变的回调函数,返回的是一个新的Promise实例,也就是Promise可以链式书写的原因。
<script>
const p = new Promise(function(resolve,reject){
setTimeout(()=>{
const time = new Date().getTime()
if(time%2==0){
resolve('成功的数据,time='+time)
}else {
reject('失败的数据,time='+time)
}
})
})
p.then((value)=>{
//fulfilled(已成功)的状态
console.log(value)
},(res)=>{
//rejected(已失败)的状态
console.log(res)
})
</script>
//走resolve,打印
成功的数据,time=1722001440362
//走reject,则打印
失败的数据,time=1722001367327
- catch()用于指定发生的错误回调,一般通过catch替代then中的第二个参数。
<script>
const p = new Promise(function(resolve,reject){
setTimeout(()=>{
const time = new Date().getTime()
if(time%2==0){
resolve('成功的数据,time='+time)
}else {
reject('失败的数据,time='+time)
}
})
})
p.catch((value)=>{
console.log(value)
})
</script>
//如果走resolve就没有打印
//走是的reject
失败的数据,time=1722001511851
- finally()用来指定不管Prormise对象状态最后如何,都会执行的操作。
<script>
const p = new Promise(function(resolve,reject){
setTimeout(()=>{
const time = new Date().getTime()
if(time%2==0){
resolve('成功的数据,time='+time)
}else {
reject('失败的数据,time='+time)
}
})
})
p.then((value)=>{//resolved(已成功)的状态
console.log(value)
}).catch((value)=>{
console.log(value)
}).finally(()=>{
console.log('end')
})
</script>
//走resolve,打印
成功的数据,time=1722001602184
end
//走reject,则打印
失败的数据,time=1722001795933
end
回调地狱(多个串联的异步操作)
<script>
setTimeout(()=>{
console.log(1)
setTimeout(() => {
console.log(2)
setTimeout(() => {
console.log(3)
}, 3000);
}, 2000);
},1000)
</script>
- promise解决回调地狱
<script>
function getData(){
return new Promise((resolve,reject)=>{
setTimeout(() => {
console.log(1)
resolve(2)
}, 1000);
})
}
getData().then((value)=>{
return new Promise((resolve,reject)=>{
setTimeout(() => {
console.log(value)
resolve(3)
}, 2000);
})
}).then((value)=>{
return new Promise((resolve,reject)=>{
setTimeout(() => {
console.log(value)
}, 3000);
})
})
</script>
//打印
1
2
3
Promise 聚合
Promise 聚合的返回值都是返回一个新的Promise对象
-
Promise.all
将多个Promise实例包装成一个新的Promise实例
<script>
let p1 = new Promise((resolve,reject)=>{
resolve('sucess01')
})
let p2 = new Promise((resolve,reject)=>{
// resolve('sucess02')
reject('fail02')
}).catch((res)=>{
console.log('失败数据')
})
let p3 = new Promise((resolve,reject)=>{
resolve('sucess03')
// reject('fail03')
})
//参数可以不是数组,但是必须是iterator
let pAll=Promise.all([p1,p2,p3])
console.log(pAll)
//pAll的状态由p1,p2,p3来决定,只有三个都成功,pAll才会成功
//只要有一个失败,就是失败,失败会返回第一个失败的数据
//如果作为参数的实例,自己定义了catch方法,那么它一旦rejected,不会触发pAll的catch方法
pAll.then((res)=>{
console.log('pAll.then:'+res)
}).catch((errors)=>{
console.log('pAll.catch:'+errors)
})
//多个请求合并在一起,按顺序输出
function getBannerList() {
return new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('轮播图的数据')
}, 1000);
})
}
function getMusicList() {
return new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('歌曲列表的数据')
}, 2000);
})
}
function getCatecList() {
return new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('歌单分类的数据')
}, 3000);
})
}
function initLoad(){
let All = Promise.all([getBannerList(),getMusicList(),getCatecList()])
console.log(All)
All.then((value)=>{
console.log(value)
})
}
initLoad()
</script>
- Promise.race
<script>
let p1 =new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('p1成功')
}, 2000);
})
let p2 =new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('p2成功')
}, 1000);
})
//调用
const prace = Promise.race([p1,p2])
prace.then((value)=>{
console.log(value)
})
//Promise.race:只要实例中有一个先改变的状态,
//就会把这个实例的参数的返回值传给prace的回调函数
//如果是then,先变化的都会获取到,如果catch第二个变化即使是rejected也不能捕捉到
//使用场景:请求超时提示
function request() {
return new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('请求成功')
}, 4000);
})
}
function timeout() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('网络不佳,请求超时')
}, 3000);
})
}
Promise.race([request(),timeout()]).then((value)=>{
console.log(value)
}).catch((res)=>{
console.log(res)
})
</script>
- Promise.any
let promise1 = Promise.reject(0);
let promise2 = new Promise((resolve) => setTimeout(resolve, 50, 'fast'));
let promise3 = new Promise((resolve, reject) => setTimeout(reject, 100, 'slow'));
Promise.any([promise1, promise2, promise3]).then((value) => {
console.log(value); // "fast",因为 promise2 最快成功
}).catch((errors) => {
// 如果所有 promise 都失败了,或者没有 promise 被传入,则执行此代码块
console.log(errors);
// 如果所有 promise 都失败了,则 errors 是一个 AggregateError,会以 AggregateError 拒绝,包含所有失败的原因。
});
Promise封装ajax
<script>
function getJSON(url) {
return new Promise((resolve, reject) => {
//创建一个实例对象
let xhr=new XMLHttpRequest()
//新建一个http请求
xhr.open('GET',url,true)
//发送http请求
xhr.send(null)
//设置状态的监听函数
xhr.onreadystatechange=function(){
if(xhr.readyState!==4)return
//当请求成功或者失败的,需要返回promise实例的状态
if(xhr.status>=200||xhr.status<300){
resolve(xhr.response)//返回请求结果
}else {
reject(new Error(xhr.statusText))
}
}
//设置错误监听函数
xhr.onerror=function(){
reject(new Error(xhr.statusText))
}
//设置响应数据类型
xhr.responseType = 'json'
})
}
getJSON('https://home.firefoxchina.cn/').then((value)=>{
console.log(value)
}).catch(res=>{
console.log(res)
})
</script>