一.基本理解与基本用法
1.基本理解
异步编程,可以执行多个promise函数
async函数返回一个 Promise 对象,可以使用then方法添加回调函数。
当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
①
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value); //等待promise执行完再执行
}
asyncPrint('hello world', 50); //50秒后输出hello world
②
由于async函数返回的是promise函数,上述例子也可以写为
async function timeout(ms) {
await new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value);
}
asyncPrint('hello world', 50);
③
function time(){
return new Promise(function(resolve){
setTimeout(resolve,2000,"延迟");
})
}
async function timeout(){
const one=await time();
console.log("12345");
return one;
}
timeout().then(function(res){
console.log(res);
})
2.基本用法
function getName(){
const promise=new Promise(function(resolve,reject){
try{
setTimeout(resolve,1000,"张三");
}
catch(err){
reject(err);
}
});
return promise;
}
function getNametwo(){
const promise=new Promise(function(resolve,reject){
try{
setTimeout(resolve,1000,"男");
}
catch(err){
reject(err);
}
});
return promise;
}
async function Name(){
const one=await getName();
const two=await getNametwo(); //若one和two未加await输出如下图
//执行多个promise,最后返回的是一个对象
return{
name:one,
sex:two
} //输出{name: "张三", sex: "男"}
}
console.log(Name()); //输出结果如下图2,返回一个promise对象,then catch finally都可以使用
Name().then(function(res){
console.log(res);
})
3.async函数的编写方式
//函数声明
async function getData(){};
//函数表达式
const data=async function(){};
//对象
let obj={async getData(){}};
obj.getData().then()
二.await命令
正常情况下,await命令后面是一个 Promise 对象,返回该对象的结果。
如果不是 Promise 对象,就直接返回对应的值。
async function f() {
// 等同于
// return 123;
return await 123;
}
f().then(v => console.log(v))
// 123
上面代码中,await命令的参数是数值123,这时等同于return 123。
await命令后面的 Promise 对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到。
async function f() {
await Promise.reject('出错了');
}
f().then(v => console.log(v))
.catch(e => console.log(e))
// 出错了
注意,上面代码中,await语句前面没有return,但是reject方法的参数依然传入了catch方法的回调函数。这里如果在await前面加上return,效果是一样的。
任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。
async function f() {
await Promise.reject('出错了');
await Promise.resolve('hello world'); // 不会执行
}
上面代码中,第二个await语句是不会执行的,因为第一个await语句状态变成了reject。
有时,我们希望即使前一个异步操作失败,也不要中断后面的异步操作。这时可以将第一个await放在try…catch结构里面,这样不管这个异步操作是否成功,第二个await都会执行。
async function f() {
try {
await Promise.reject('出错了');
} catch(e) {
}
return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v))
// hello world
另一种方法是await后面的 Promise 对象再跟一个catch方法,处理前面可能出现的错误。
async function f() {
await Promise.reject('出错了').catch(e => console.log(e));
return await Promise.resolve('hello world');
}
f().then(v => console.log(v))
// 出错了
// hello world
三.异常处理
如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject。
async function f() {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
}
f().then(v => console.log(v))
.catch(e => console.log(e))
// Error:出错了
解决方法也是将其放在try…catch代码块之中。
async function f() {
try {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
} catch(e) {
}
return await('hello world');
}
await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try…catch代码块中。
需要注意的问题
① 如果await后边的promise返回reject,直接将整个await抓异常
② 如果多个await之间有继发关系,就让他们一个一个走,如果他们没有关系,就让他们同时触发
async function getData(){
try{
let number=await new Promise(function(resolve,reject){
try{
setTimeout(resolve,1000,1);
}
catch(err){
reject(err);
}
});
let data=await new Promise(function(resolve,reject){
try{
setTimeout(resolve,1000,"数据");
}
catch(err){
reject(err);
}
});
return{
number:number,
data:data
}
}
catch(err){
console.log(err);
}
}
getData().then(function(res){
console.log(res);
})
多个await之间没有继发关系
await Promise.all()
function getName(){
return new Promise(function(resolve){
setTimeout(resolve,1000,"张三")
})
}
function getSex(){
return new Promise(function(resolve){
setTimeout(resolve,1000,"男")
})
}
function getAge(){
return new Promise(function(resolve){
setTimeout(resolve,1000,20)
})
}
async function name(){
let data=await Promise.all([getName(),getSex(),getAge()]);
return data;
}
name().then((res)=>{
console.log(res);
})
将上述代码改为继发
function getName(){
return new Promise(function(resolve){
setTimeout(resolve,1000,"张三")
})
}
function getSex(name){
return new Promise(function(resolve){
setTimeout(resolve,1000,"男")
})
}
function getAge(age){
return new Promise(function(resolve){
setTimeout(resolve,1000,20)
})
}
async function name(){
let name=await getName();
let sex=await getSex(name);
let age=await getAge(sex);
return age; //隔三秒才会输出age
}
name().then((res)=>{
console.log(res);
})