Promise的介绍与使用——学习笔记
Promise
Promise是JS中进行异步编程的新解决方案(以前使用回调函数来解决异步编程)
从语法上来说:Promise是一个构造函数
从功能上来说:Promise对象用来封装一个异步操作并且可以获取起成功或失败的结果值
一、Promise状态改变
Promise共有三种状态pending、resolved(fulfilled)、rejected。
状态的改变只有两种可能:
-
pending——>resolved -
pending——>rejected
如果Promise的状态已经发生了改变,就不会在改变了。
二、Promise基本使用
通过resolved设置状态为成功,通过rejected设置状态为失败
通过then方法对成功和失败的状态进行处理
例子1:点击按钮,1s后显示是否中奖(30%的中奖概率)
<body>
<div>
<h2>Promise 初体验</h2>
<hr />
<button id="btn">点击抽奖</button>
</div>
<script>
//生成随机数
function rand(m,n){
return Math.ceil(Math.random() * (n-m+1)) + m-1;
}
// 获取元素
const btn = document.querySelector('#btn')
// 绑定事件
btn.addEventListener('click', function() {
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// 获取从1-100的一个随机数
let n = rand(1,100)
// 判断
if (n <= 30) {
resolve(n) // 将 promise 对象的状态设置为【成功】
} else {
reject(n) // 将 promise 对象的状态设置为【失败】
}
}, 1000);
})
// console.log(p)
// 调用then方法
p.then((value) => {
alert(`success:${value}`)
}, (reason) => {
alert(`fail:${reason}`)
})
})
</script>
</body>
例子2:使用Promise封装一个ajax的get请求
function sendAJAX(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.responseType = 'json'
xhr.open('GET', url)
xhr.send()
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response)
} else {
reject(xhr.status)
}
}
}
})
}
sendAJAX('https://api.apiopen.top/getJoke').then(res => {
console.log(res)
}, reason => {
console.log(reason)
})
三、Promise中的API
3.1、Promise构造函数
-
executor函数:执行器(resolve,reject) => {} -
resolve函数:内部定义成功时调用该函数 -
reject函数:内部定义失败时调用该函数
3.2、then&catch
3.2.1、Promise.prototype.then方法
(onResolved, onRejected) => {}
-
onResolved函数: 成功的回调函数 -
onRejected函数:失败的回调函数
3.2.2、Promise.prototype.catch方法
(onRejected) => {}
onRejected函数:失败的回调函数,相当于then()方法的语法糖
let p = new Promise((resolve, reject) => {
console.log('11')
reject('error')
})
console.log('22')
// p.then(value => {}, reason => {})
p.catch(reason => {
console.log(reason)
})
注意:在Promise中的代码是同步调用的,所以上面的代码会先输出11再输出22
3.3、Promise.resolve方法
(value) => {} 快速返回一个Promise对象
value成功的数据或Promise对象
-
传入的参数为非
Promise类型的对象,则返回结果为成功 -
传入的参数为
Promise对象,则参数结果决定了resolve的结果
let p1 = Promise.resolve(1)
let p2 = Promise.resolve(new Promise((resolve, reject) => {
reject('error')
}))
console.log(p2)
p2.catch(reason => {
console.log(reason)
})
3.4、Promise.reject方法
(resone) => {}
resone:失败的原因,方法会返回一个失败的对象,不论里面的数据是成功还是失败
let p = Promise.reject('3')
let p1 = Promise.reject(new Promise((resolve, reject) => {
resolve(3223)
}))
console.log(p)
console.log(p1)
3.5、Promise.all方法
(promises) => {}
返回一个新的Promise,只有所有Promise都成功才成功,只要有一个失败了就直接失败
promsies:包含n个Promsie的数组
let p1 = new Promise((resolve, reject) => {
resolve('ok')
})
let p2 = Promise.resolve('success')
let p3 = Promise.reject('fail')
const result = Promise.all([p1, p2, p3])
console.log(result)
3.6、Promise.race方法
(promises) => {}
返回一个新的Promise,第一个完成的Promise的结果状态就是最终的结果状态
promises:包含n个Promsie的数组
let p1 = new Promise((resolve, reject) => {
// setTimeout(() => {
resolve('OK');
// }, 1000);
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
//调用
const result = Promise.race([p1, p2, p3]);
console.log(result);
四、Promise的关键问题
4.1、Promise的状态如何改变
-
resolve(value):如果当前是pending就会变为resolved -
reject(reason):如果当前是pending就会变为rejected -
抛出异常:如果当前是
pending就会变为rejected
4.2、Promise指定多个成功或失败回调函数,都会调用吗
当Promise改变为对应状态时都会调用
let p = new Promise((resolve, reject) => {
resolve('OK');
});
///指定回调 - 1
p.then(value => {
console.log(value);
});
//指定回调 - 2
p.then(value => {
alert(value);
});
4.3、改变Promise状态和指定回调函数谁先谁后
正常情况是先制定回调再改变状态,也可以先改变状态再指定回调
在执行器中直接调用resolve()/reject()或者延迟更长的时间在调用then()方法都可以使先改变状态再指定回调
如果先指定回调,当状态发生改变时,回调函数就会调用,得到数据
如果先改变状态,那当指定回调时,回调函数就会调用,得到数据
let p = new Promise((resolve, reject) => {
// setTimeout(() => {
resolve('OK');
// }, 1000);
});
p.then(value => {
console.log(value);
},reason=>{
})
4.4、Promise.prototype.then()返回的新Promise结果状态由什么决定
-
由
then()指定的回调函数执行结果决定。-
如果抛出异常,新的
Promise变为rejected、reason为抛出的异常 -
如果返回的是非
Promise的任意值,新Promise变为resolved -
如果返回的是另一个新
Promise,此Promise的结果就会成为新Promise的结果 -
如果没有返回值,则会返回一个成功状态的
Promise值为undefined
-
let p = new Promise((resolve, reject) => {
// setTimeout(() => {
resolve('ok')
// }, 1000);
})
let result = p.then(value => {
console.log(value)
// 出错
// throw 'error'
// 不是promise
// return 521
// promise 对象
// return new Promise((resolve, reject) => {
// // resolve('success')
// reject('fail')
// })
}, reason => {
console.warn(reason);
})
console.log(result)
4.5、Promise如何串连多个操作任务
Promise的then()返回一个新的Promise,可以看成then()的链式调用。通过then的链式调用串联多个同步或异步任务
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok')
}, 1000);
})
p.then(value => {
return new Promise((resolve, reject) => {
resolve('success')
})
}).then(value => {
console.log(value)
}).then(value => {
console.log(value)
})
4.6、Promise异常穿透
当使用Promise的then链式调用时,可以在最后指定失败的回调,前面的操作出了任何异常,都会传到最后失败的回调中处理
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
// reject('Err');
}, 1000);
});
p.then(value => {
console.log(111);
}).then(value => {
throw '失败啦!';
// console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});
4.7、中断Promise链
当使用Promise的then链式调用时,在中间中断后就不能再调用后面的回调,如果还想在后面调用回调函数,可以在回调函数中返回一个pendding状态的Promise对象
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(
// value => {
// console.log(111);
// 有且只有一个方式
// return new Promise(() => {});
// }
).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});

浙公网安备 33010602011771号