Skip to content

async/await 是语法糖,异步的本质还是回调函数

async/await 语法

  • 异步回调容易产生 callback hell(回调地狱)
  • Promise then catch 链式调用,但也是基于回调函数
  • async/await 是同步语法,彻底消灭回调函数,代码演示:
js
//加载图片
function loadImg(src) {
  const p = new Promise((resolve, reject) => {
    const img = document.createElement('img');
    img.onload = () => {
      resolve(img);
    };
    img.onerror = () => {
      const err = new Error(`图片加载失败 ${src}`);
      reject();
    };
    img.src = src;
  });
  return p;
}
const src1 =
  'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png';
const src2 =
  'https://box.bdimg.com/static/fisp_static/common/img/searchbox/logo_news_276_88_1f9876a.png';
// !用于解决报错 Uncaught TypeError: "https..." is not a function is not a function
!(async function () {
  // 同步的写法
  const img1 = await loadImg1(); //也可以直接用 loadImg(src1)
  console.log(img1.width, img1.height);
  const img2 = await loadImg2(); //也可以直接用 loadImg(src2)
  console.log(img2.width, img2.height);
})();
async function loadImg1() {
  const img1 = await loadImg(src1);
  return img1;
}
async function loadImg2() {
  const img2 = await loadImg(src2);
  return img2;
}

async/await 和 Promise 的关系

  • async/await 是消灭异步回调的终极武器
  • 但和 Promise 并不互斥,反而两者相辅相成
  • 执行 async 函数,返回的是 Promise 对象
js
async function fn1() {
  return 100;
  // return Promise.resolve(200)
}
const res1 = fn1(); // 执行 async 函数,返回 Promise 对象
console.log('res1', res1); // res1 Promise
res1.then((data) => {
  console.log('data1', data); // data1 100
});
  • await 相当于 Promise 的 then
js
async function fn1() {
  return 100;
  // return Promise.resolve(200)
}
!(async function () {
  const p1 = Promise.resolve(300);
  const data = await p1; // await 相当于 Promise then
  console.log('data', data); // data 300
})();
!(async function () {
  const data1 = await 400; // 直接返回 400
  console.log('data', data1); // data 400
})();
!(async function () {
  const data2 = await fn1(); // await 相当于 Promise.resolve(100)
  console.log('data', data2); // data 100
})();
  • try...catch 可捕获异常,代替了 Promise 的 catch
js
!(async function () {
  const p4 = Promise.reject('err'); // rejected状态
  try {
    const res4 = await p4;
    console.log('res4', res4); // 不执行
  } catch (e) {
    console.error('err4', e); //err4 err try…catch 相当于 Promise catch
  }
})();
// 没有 try…catch 无法捕获错误
!(async function () {
  const p5 = Promise.reject('err1'); // rejected状态
  const res5 = await p5; // await -> then,下面不会执行
  console.log('res5', res5); // 不执行
})();

异步的本质

  • async/await 是消灭异步回调的终极武器
  • JS 还是单线程,还得是有异步,还得是基于 event loop
  • async/await 只是一个语法糖,代码演示:
js
async function async1() {
  console.log('async1 start'); // step 2
  await async2(); //undefined
  // await 的后面,都可以看做是 callback 里的内容,即异步
  // 类似 event loop,setTimeout(function(){ console.log('async1 end')})
  // 或 Promise.resolve().then(()=>{console.log('async1 end')})
  console.log('async1 end'); // step 5
}
async function async2() {
  console.log('async2'); // step 3
}
console.log('script start'); // step 1
async1();
console.log('script end'); // step 4
// 同步代码已经执行完(event loop)
// script start
// async1 start
// async2
// script end
// async1 end

再看一个例子:

js
async function async1() {
  console.log('async1 start'); // step 2
  await async2();
  // 下面都是异步回调 callback 的内容
  console.log('async1 end'); // step 5
  await async3();
  // 下面都是异步回调 callback 的内容
  console.log('async1 end 2'); // step 7
}
async function async2() {
  console.log('async2'); // step 3
}
async function async3() {
  console.log('async3'); // step 6
}
console.log('script start'); // step 1
async1();
console.log('script end'); // step 4
// 同步代码已经执行完(event loop)
// script start
// async1 start
// async2
// script end
// async1 end
// async3
// async1 end 2

补充 for ... of 异步的使用

  • for ... in (以及 forEach for )是常规的同步遍历
  • for ... of 常用于异步的遍历
js
function muti(num) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(num * num);
    }, 1000);
  });
}
const nums = [1, 2, 3];
nums.forEach(async (i) => {
  // 1秒后同步执行
  const res = await muti(i); // 相当于 Promise 的 then
  console.log(res); // 1 4 9
});
!(async function () {
  for (let i of nums) {
    // 1秒执行一个
    const res = await muti(i); // 相当于 Promise 的 then
    console.log(res); // 1 4 9
  }
})();

基于 MIT 许可发布