promise解决异步编程:
1. 旧方案:回调函数
2. Promise:是一个构造函数,内部封装异步操作
异步操作主要包括:fs文件读取操作,定时器,数据库操作,AJAX
3. promise新建之后会立即执行
promise
异步操作:
文件读取—用promise封装文件读取操作----02-fs文件读取.js
AJAX------用promise封装AJAX发送网络请求操作-03-ajax.html
promise构造函数的方法:
then/catch/finally ---p实例可以使用
Promise对象的方法:
resolve/reject
all/race
allSettled
any
一、基础用法
let p = new Promise(function(resolve,reject){
if(true){
resolve()
} else {
reject()
}
})
resolve函数的作用
1. 将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved)
2. 在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject函数的作用
1. 将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected)
2. 在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
二、实例对象的属性
promise的状态–实例对象的一个属性【promiseState】
pending 未决定的
resolve /fullfilled 成功
reject 失败
promise对象的值–实例中的另一个属性【PromiseResult】
保存着对象【成功/失败】的结果
resolve
reject
三、promise流程图
四、promise实例方法then/catch/finally
p.then方法
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
});
then方法的链式调用:
第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。
p.catch方法
p.then((val) => console.log('fulfilled:', val))
.catch((err) => console.log('rejected', err));
// 等同于
p.then((val) => console.log('fulfilled:', val))
.then(null, (err) => console.log("rejected:", err));
五、Promise对象方法 resolve/reject/all/race/allSettled
Promise.resolve方法
- Promise.resolve(‘foo’) 等价于 new Promise(resolve=>resolve(‘foo’))
- 如果传入的参数是:非promise类型的对象,则返回的结果为成功的promise对象
- 如果传入的参数是Promise对象,则参数的结果决定了resolve的结果
let p1 = Promise.resolve('foo')
let p2 = Promise.resolve(new Promise((resolve, reject) => {
reject('错误')
}))
console.log('promise的resolve方法', p1, p2);
// 错误捕获
p2.catch(error => {
console.log('失败原因', error);
})
Promise.reject 方法
const p = Promise.reject('出错了');
// 等同于
const p = new Promise((resolve, reject) => reject('出错了'))
p.then(null, function (s) {
console.log(s)
});
// 出错了
console.log(p)
// 上面代码生成一个 Promise 对象的实例p,状态为rejected,回调函数会立即执行。
// Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。
Promise.reject('出错了')
.catch(e => {
console.log(e === '出错了')
})
// true
Promise.all/race方法
接受参数是一个数组
p1,p2,p3是promise实例
p的状态由p1、p2、p3决定,分成两种情况。
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,
此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,
此时第一个被reject的实例的返回值,会传递给p的回调函数。
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)
–race用法基本同all
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
Promise.allSettled
使用场景:
有时候,我们希望等到一组异步操作都结束了,不管每一个操作是成功还是失败,再进行下一步操作。
与race类似,接受[p1,p2,p3]作为参数
可以等待所有的p结果出来之后返回,一个fullfilled则结果为fullfilled,全部为reject才为reject
const p1 = Promise.resolve(42);
const p2 = Promise.reject(-1);
const allSettledPromise = Promise.allSettled([p1, p2]);
allSettledPromise.then(function (results) {
console.log(results);
});
// [
// { status: 'fulfilled', value: 42 },
// { status: 'rejected', reason: -1 }
// ]
它的回调函数接收到的参数是数组results,
该数组的每个成员都是一个对象,对应传入Promise.allSettled()的数组里面的两个 Promise 对象
使用实例:
const promises = [ fetch('index.html'), fetch('https://does-not-exist/') ];
const results = await Promise.allSettled(promises);
// 过滤出成功的请求
const successfulPromises = results.filter(p => p.status === 'fulfilled');
// 过滤出失败的请求,并输出原因
const errors = results
.filter(p => p.status === 'rejected')
.map(p => p.reason);
关键问题:
1. 如何修改promise对象的状态?
![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sVjzad8h-1675172227808)(assets/2.jpg)\]](https://img-blog.csdnimg.cn/94ddcdcb39e042d18b58171ca8528df5.png)
2. 一个promise指定多个成功/失败回调函数,都会调用吗?
当promise改变为对应状态时都会调用
![在这里插入图片描述](https://img-blog.csdnimg.cn/97fefb74d6cf4d9b819723cb2c348055.png)
3. 改变promise状态和指定回调函数谁先谁后?
都有可能。
如果执行器函数excutor中包裹的是异步任务例如定时器(resolve()),此时先指定回调函数,当状态发生改变的时候,
回调函数会调用。
![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ycVDh9KO-1675172227811)(assets/4.jpg)\]](https://img-blog.csdnimg.cn/675c464408774c6ca16c9b0b4f6a2e0d.png)
4. p.then()返回的新promise的结果由什么决定?
简单回答:由then执行的回调函数的执行结果决定。
5. promise如何串联多个任务?
promise的then()返回一个新的promise,可以开成then()的链式调用
通过then串联多个同步或者异步任务
6. promise异常穿透?
// catch在最后捕获异常,异常穿透
p.then(value=>{}).then(value=>{}).catch(reason=>{
console.log('捕获异常')
})
7. 如何中断promise链?
promise链:.then.then.then ----then 的链式调用
当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数。
解决办法:在回调函数中返回一个pending状态的promise对象
p.then(value=>{
return new Promise(()=>{}) // pending 状态的promise--中断-后面的then不再执行
}).then(value=>{}).then(value=>{})
async与await函数
1. async函数
async函数的返回值是一个promise对象
返回的promise对象结果由async函数执行的返回值决定
和then方法的返回规则一样
2. await函数
await必须写在async函数当中
await函数后面一般跟的是promise对象,也可跟其他的值
await的promise如果失败了,会抛出异常,需要通过try...catch 进行捕获处理
async function handler(){
try{
await new Promise((resolve,reject)=>{
throw "error"
})
}catch(e){
console.log('抛出错误',e)
}
}