es6 —— 理解async函数

async函数
① 特点:
  1. 内置执行器
  2. 更好的语义
  3. 更广的适用性
  4. 返回值时Promise
② 基本用法

async函数返回一个Promise对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先去执行await后面的方法,当在执行方法时遇到异步操作时,先返回(即先return),然后再去执行异步操作。等到第一个await后的方法执行完毕后再执行后面的语句。

在下面例子中,先执行getName方法,在getName方法中遇到异步操作(即计时器),故先返回,即输出Promise对象(即输出getinfo()的返回值,但promiseValue值为null,等到所有语句执行完毕后,promiseValue值为所有Promise的值的集合)。再继续执行异步操作。等到getName方法执行完毕后再执行getSex方法,等到getSex方法执行完后再输出1111
输出:
在这里插入图片描述

 function getName(){
         const promise=new Promise(function (resolve,reject){
         try{
             console.log("hello1");
             console.log("hello11");
         setTimeout(function () {
             console.log("计时器1");
             resolve("张三")
             console.log("计时器11");
         },500);
         }
         catch(err){
         reject(err)
         }
         });
         return promise;
         }
         function getSex(){
         const promise=new Promise(function (resolve,reject){
         try{
             console.log("hello2");
         setTimeout(function () {
             console.log("计时器2");
             resolve("男")
         },1000);
         }
         catch(err){
         reject(err)
         }
         });

         return promise;
         }
         async function getinfo(){
         const name= await getName();
         const sex=await getSex();
         console.log(1111);
         return {
         name:name,
         sex:sex
         };
         }
         console.log(getinfo());
③ 语法以及Promise对象的状态变化
  1. async函数返回一个Promsie对象(无论是否有return语句)
  2. async函数内部return语句返回的值会成为then方法回调函数的参数(resolve/reject)。
  3. async函数返回的Promise对象必须等待内部所有await命令后面的Promise对象执行完才会发生状态改变,除非遇到return语句或者抛出错误。即async函数内部的异步操作执行完后才会执行then方法的回调函数
④ await命令
  1. 正常情况下,await命令后面是一个Promise对象,返回该对象的结果(返回promise对象执行的返回值),如果不是Promise对象就直接返回对应的值。
  2. 任何一个await语句后面的Promise对象变为reject状态,那么整个async函数会中断执行。
  3. ① 如果想要一个异步操作失败不影响后面的异步操作,可将出错的异步操作放置try{}..catch(){}中,这样不管该异步操作失败/成功都不会影响后续代码的执行 ② 另一个方法是在await后面的Promise对象后加一个catch方法,处理前面可能出现的错误。如果catch中有异步操作会先执行后续代码,最后再执行catch中的异步操作。
 function sleep(interval) {
            return new Promise(resolve => {
                setTimeout(resolve, interval);
        })
        }
// 用法
        async function one2FiveInAsync() {
        for(let i = 1; i <= 5; i++) {
            console.log(i);
            await sleep(1000);//当该方法执行完后才会i++
        }
        return "hello";
    }
        console.log(one2FiveInAsync());
//出错处理方法
//①
async function f() {
  try {
    await Promise.reject('出错了');//将该Promise对象错误捕捉,不会影响后续操作
  } catch(e) {
  }
  return await Promise.resolve('hello world');
}
f().then(v => console.log(v))// hello world

//②
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
⑤ 错误处理
  1. 如果await后面的异步操作出错,那么等同于async函数返回的Promise被reject。故可通过then方法的回调函数接受到await后面异步操作的错误信息。
  2. 为了避免由于一个await后面的异步操作导致后续代码无法执行,可将其放在try{}catch{}代码块中。
⑥ async函数使用注意点
  1. 最好将await命令放在try...catch代码块中
  2. 如果有多个await命令,且其后面的异步操作不存在继发关系,最好让它们同时触发。
let foo = await getFoo();
let bar = await getBar();//该例子中,等到上一条语句执行完后才会执行这条语句。这样比较耗时。
//两种解决方案
//1
let [foo, bar] = await Promise.all([getFoo(), getBar()]);

//2
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
  1. await命令只能用在async函数中,如果用在普通函数会报错
  2. async函数可以保留运行堆栈
//下面代码中,a的内部一个异步任务b(),当b()运行时,函数a不会终端执行,再b()执行完毕后,a可能早已经执行完毕。此时b函数所在的上下文环境消失。如果b()或c()报错,错误堆栈将不包括a()
const a = () => {
  b().then(() => c());
};

//改进
//当b执行的时候,a会暂停执行。上下文环境保存着。当b()/c()报错时,错误堆栈将包括a()
const a = async ()=>{
	await b();
	c();
}
发布了72 篇原创文章 · 获赞 72 · 访问量 6317

猜你喜欢

转载自blog.csdn.net/weixin_43314846/article/details/102802725