promise
promise状态
promise总是处于以下三种状态之一:
pending:初始状态fulfilled/resolved:表示成功rejected:表示失败
状态有一些特性:
- 只能通过执行函数修改
- 外部无法读取
- 外部无法修改
promise.prototype.then
为
promise实例添加处理程序的主要方法,接收的两个参数分别表示进入fulfilled/resolved或rejected状态时被调用,且二者互斥。两个参数可选,但必须是函数类型,非函数类型会被忽略。一个promise实例可以有任意多个处理程序(任意多个then调用)
promise.prototype.catch
等价于promise.prototype.then(null,onrejected)
promise.prototype.finally
无论状态是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.resolve()包装成一个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是有差异的。
总结
到此这篇关于es6中promise、async、await用法超详细讲解指南的文章就介绍到这了,更多相关es6 promise、async、await内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论