Promise是es6引入的异步编程新解决方案,Promise实例和原型上有reject、resolve、all、then、catch、finally等多个方法,语法上promise就是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果,本篇文章主要介绍了ES6中的Promise对象与async和await方法,创作不易,如果能帮助到带大家,欢迎收藏+关注 哦 ????
????????文章目录
Promise
promise状态
执行次序
示例1
示例2
链式调用
链式传值
catch对调用链的影响
catch处在最后
catch处在中间
async & await
async
await
Promise
promise状态
Promise
总是处于以下三种状态之一:
pending
:初始状态fulfilled/resolved
:表示成功rejected
:表示失败
状态有一些特性:
- 只能通过执行函数修改
- 外部无法读取
- 外部无法修改
为
Promise
实例添加处理程序的主要方法,接收的两个参数分别表示进入fulfilled/resolved
或rejected
状态时被调用,且二者互斥。两个参数可选,但必须是函数类型,非函数类型会被忽略。一个Promise
实例可以有任意多个处理程序(任意多个then
调用)
等价于(null,onRejected)
无论状态是fulfilled/resolved
还是rejected
都会执行,但无法得知具体的状态(状态无关),一般主要用于清理工作
执行次序
示例1
-
const p = new Promise(resolve => {
-
console.log('1. excute promise');
-
setTimeout(() => {
-
console.log('3. before resolve')
-
resolve();
-
console.log('4. after resolve')
-
}, 100);
-
})
-
-
p.then(() => {
-
console.log('5. execute resolve')
-
}).then(()=>{
-
console.log('6. then2')
-
}).then(()=>{
-
console.log('7. then3')
-
}).finally(()=>{
-
console.log('8. finally')
-
});
-
console.log('2. sync then')
-
-
/**
-
result:
-
1. excute promise
-
2. sync then
-
3. before resolve
-
4. after resolve
-
5. execute resolve
-
6. then2
-
7. then3
-
8. finally
-
*/
'
运行
示例2
-
const p = new Promise(resolve => {
-
setTimeout(() => {
-
resolve();
-
}, 100);
-
})
-
-
p.then(()=>{
-
console.log('then1')
-
}).then(()=>{
-
console.log('then2')
-
}).then(()=>{
-
console.log('then3')
-
}).then(()=>{
-
console.log('then4')
-
}).then(()=>{
-
console.log('then5')
-
});
-
console.log('async then')
-
-
/**
-
result:
-
async then
-
then1
-
then2
-
then3
-
then4
-
then5
-
*/
'
运行
这个示例中then1
、then2
、then3
、then4
、then5
相当于是同步执行的
链式调用
then
的链式调用是Promise
最常见的用法,具体方式是每个执行器返回一个Promise
实例,则后续每个then
都会等待前一个落定后再执行,即异步的串行化。以此来解决异步的回调地狱难题。
es6
规范不支持Promise
终止与进度查询,原因是这样会使得Promise
变得过于复杂。
链式传值
-
const p = new Promise(resolve => {
-
setTimeout(() => {
-
resolve(100);
-
}, 100);
-
})
-
-
p.then(value => {
-
console.log(value)
-
return value + 1;
-
}).then(value => {
-
console.log(value)
-
return new Promise(resolve => {
-
setTimeout(() => {
-
resolve(value + 1)
-
}, 3000);
-
});
-
}).then(value => {
-
console.log(value)
-
return value + 1;
-
}).then(value => {
-
console.log(value)
-
return value + 1;
-
}).then(value => {
-
console.log(value)
-
return value + 1;
-
});
-
-
/**
-
100
-
101
-
102 等待3秒
-
103
-
104
-
*/
'
运行
如果执行函数返回的是一个
Promise
对象,则后续的调用会等待该对象落定后触发,通过resolve
方式传值;如果不是,则后续立即触发,通过return
语句向后传值
catch对调用链的影响
catch
处在最后
-
const p = new Promise(resolve => {
-
setTimeout(() => {
-
resolve(100);
-
}, 100);
-
})
-
-
p.then(value => {
-
console.log(value)
-
return value + 1;
-
}).then(value => {
-
console.log(value)
-
return new Promise((resolve, reject) => {
-
setTimeout(() => {
-
reject('fail')
-
}, 3000);
-
});
-
}).then(value => {
-
console.log(value)
-
return value + 1;
-
}).then(value => {
-
console.log(value)
-
return value + 1;
-
}).then(value => {
-
console.log(value)
-
return value + 1;
-
}).catch(err => {
-
console.log('catch', err);
-
return new Promise((resolve, reject) => {
-
setTimeout(() => {
-
resolve(400)
-
}, 3000);
-
});
-
});
-
/**
-
100
-
101
-
catch fail
-
*/
'
运行
当catch
处在调用链最后的时候,则reject
后续的then
将不会被触发
catch
处在中间
-
const p = new Promise(resolve => {
-
setTimeout(() => {
-
resolve(100);
-
}, 100);
-
})
-
-
p.then(value => {
-
console.log(value)
-
return value + 1;
-
}).then(value => {
-
console.log(value)
-
return new Promise((resolve, reject) => {
-
setTimeout(() => {
-
reject('fail')
-
}, 3000);
-
});
-
}).then(value => {
-
console.log(value)
-
return value + 1;
-
}).catch(err => {
-
console.log('catch', err);
-
return 500;
-
}).then(value => {
-
console.log(value)
-
return value + 1;
-
}).then(value => {
-
console.log(value)
-
return value + 1;
-
});
-
/**
-
100
-
101
-
catch fail
-
*/
'
运行
catch
处在调用链中间,如果返回的不是一个Promise
对象,后续的then
将不会被触发
async & await
async
语法:
-
async function name([param[, param[, ... param]]]) {
-
statements
-
}
- name:函数名称
- param:要传递给函数的参数的名称
- statements:包含函数主体的表达式,可以使用
await
机制- 返回值:一个
Promise
,这个Promise
要么会通过一个由async
函数返回的值被解决,要么会通过一个从async
函数中抛出的(或其中没有被捕获到的)异常被拒绝
async
关键字用于声明异步函数,可以用在函数声明、函数表达式、箭头函数、方法上:
-
async function foo() {}
-
let bar = async function () {}
-
let baz = async () => {}
-
class Person{
-
async say(){}
-
}
'
运行
异步函数如果使用return
关键字返回了值,则这个值会被()
包装成一个Promise
对象:
-
async function test() {
-
return 2;
-
}
-
test().then(value => {
-
console.log(value)
-
})
-
console.log(1)
-
-
/**
-
1
-
2
-
*/
'
运行
如果函数体中抛出了异常,可以用catch
处理:
-
async function test() {
-
const result = 100 / a;
-
return result;
-
}
-
test().catch(value => {
-
console.log(value)
-
})
-
console.log(1)
-
/**
-
1
-
ReferenceError: a is not defined
-
*/
'
运行
一些资料中会说拒绝
Promise
的异常不被异步函数捕获,但在最新版的Chrome(95.0.4638.69)
、Microsoft Edge(95.0.1020.40)
、Firefox(93.0)
都是支持的:
-
async function test() {
-
return Promise.reject('error');
-
}
-
test().catch(value => {
-
console.log(value)
-
})
-
console.log(1)
-
/**
-
1
-
error
-
*/
'
运行
await
语法:
[返回值] = await 表达式;
- 表达式:一个Promise对象或者任何要等待的值
- 返回值:返回
Promise
对象的处理结果。如果等待的不是Promise
对象,则返回该值本身
在用法上,await
可以单独使用,也可以在表达式中使用:
-
async function func(){
-
console.log(await Promise.resolve('foo'))
-
}
-
func();
-
/**
-
foo
-
*/
'
运行
await
只能在async
函数内顶层使用,不支持嵌套
在使用多个
await
关注其结果,忽视其顺序有时候是个好事,因为不同的规范对于await
处理Promise
是有差异的。
???? 个人简介:某大型国企资深软件开发工程师,信息系统项目管理师、****优质创作者、阿里云专家博主、华为云云享专家,分享前端后端相关技术与工作常见问题~
???? 作 者:码喽的自我修养❣️
???? 专 栏:JavaScript深入研究???? 若有帮助,还请 关注➕点赞➕收藏 ,不行的话我再努努力????????????
更多专栏订阅推荐:
???? vue2/3 从基础到起飞
???? JavaScript深入研究
???? 前端工程搭建
???? javaScript基础✈️ HTML5与CSS3
⭐️ uniapp与微信小程序
???? 前端工作常见问题汇总
✍️ GIS地图与大数据可视化
???? 常用组件库与实用工具