(Day25) Promise 语法糖 async/await

前言

async/awaitPromise 的语法糖,最主要是提升了 Promise 在链式写法的可读性,而 async/await 能办到的 Promise 本身都能办到,所以不少教学都提到要先明白 Promise ,才会看懂 async/await

async/await 介绍:

  • async 直接翻译成中文是异步,也就是非同步的意思,若要使用 async 会将 async 放在函式旁,代表这个函式接下来会以同步方式来执行非同步的语法。

  • await 翻译成中文,则是等待, 一般是放在 async 函式中的 Promise 事件旁,代表接下来的程序码会等待 await 方法完成後才执行。

async/await 他们算是一组的,基本上使用碰上使用时机时,这两个方法都会同时被使用 ,这部分用文字说明可能不是这麽好懂,直接来使用 Promise 章节提到的 Promise 链式写法,以及 async/await 来做对比会比较好理解:

  • Promise 链式写法:
const p = new Promise((resolve) => {
  if (true) {
    resolve(`直接执行 Promise`)
  }
})

function PromiseFn(String) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      if (String.length >= 5) {
        resolve(`Promise 成功, ${String} 共 ${String.length} 个字 `)
      } else {
        reject('Promise 失败')
      }
    }, 2000);
  });
}

PromiseFn('Ryder')
  .then((res) => {
    console.log(res) // Promise 成功, Ryder 共 5 个字
    return PromiseFn('youtube')
  }).then((res) => {
    console.log(res)  // Promise 成功, youtube 共 7 个字 
    return p
  }).then((res) => {
    console.log(res) // 直接执行 Promise
  })
  • async/await 则可写成:
const p = new Promise((resolve) => {
  if (true) {
    resolve(`直接执行 Promise`)
  }
})

function PromiseFn(String) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      if (String.length >= 5) {
        resolve(`Promise 成功, ${String} 共 ${String.length} 个字 `)
      } else {
        reject('Promise 失败')
      }
    }, 2000);
  });
}

async function usePromise() {
  const data1 = await PromiseFn('Ryder');
  console.log(data1) // Promise 成功, Ryder 共 5 个字
  const data2 = await PromiseFn('youtube');
  console.log(data2) // Promise 成功, youtube 共 7 个字
  const data3 = await p
  console.log(data3); // 直接执行 Promise
}
usePromise();

扣掉 console.log 可以发现 async/await 的写法省去大量的 then() ,因此让程序码变的较容易阅读。
await 其实可以塞入其他表达式的,但是实做中通常不会这麽使用:

const p = new Promise((resolve) => {
  if (true) {
    resolve(`直接执行 Promise`)
  }
})

function PromiseFn(String) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      if (String.length >= 5) {
        resolve(`Promise 成功, ${String} 共 ${String.length} 个字 `)
      } else {
        reject('Promise 失败')
      }
    }, 2000);
  });
}

async function usePromise() {
  const data1 = await 1+1;
  console.log(data1) // 2
  const data2 = await PromiseFn('youtube');
  console.log(data2) // Promise 成功, youtube 共 7 个字
  const data3 = await p
  console.log(data3); // 直接执行 Promise
}
usePromise();

try...catch

使用 async/await 的写法 ,只要使用 awaitPromise 只要一失败,接下来会回传 Promisereject 资料,接着 await 下的程序码都不会被执行,比如:

const p = new Promise((resolve) => {
  if (true) {
    resolve(`直接执行 Promise`)
  }
})

function PromiseFn(String) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      if (String.length >= 5) {
        resolve(`Promise 成功, ${String} 共 ${String.length} 个字 `)
      } else {
        reject('Promise 失败')
      }
    }, 2000);
  });
}

async function usePromise() {
  const data1 = await PromiseFn('Ryder');
  console.log(data1) // Promise 成功, Ryder 共 5 个字
  const data2 = await PromiseFn('test');
  console.log(data2) // Promise 失败
  const data3 = await p
  console.log(data3); 
}
usePromise();

这种状况会容易造成不清楚错误来源,在维护上会较为困难,也因此 async/await 的写法,有提供另一种将 Promise 执行成功、失败分开的写法,就是 try…catchtry 专门存放执行 Promise 成功的结果,而 catch 则是执行 Promise 失败的结果,这个方法跟原生 Promise.then().catch() 十分相似,如范例:

const p = new Promise((resolve) => {
  if (true) {
    resolve(`直接执行 Promise`)
  }
})

function PromiseFn(String) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      if (String.length >= 5) {
        resolve(`Promise 成功, ${String} 共 ${String.length} 个字 `)
      } else {
        reject('Promise 失败')
      }
    }, 2000);
  });
}

async function usePromise() {
try{
  const data1 = await PromiseFn('Ryder');
  console.log(data1) //Promise 成功, Ryder 共 5 个字 
  const data2 = await PromiseFn('test'); // Promise 执行 catch
  console.log(data2) 
  const data3 = await p
  console.log(data3); 
	}
	catch (err) {
    console.log('catch', err); //catch Promise 失败
  }
}
usePromise();

要注意的是 try 中的 Promise 执行失败,是会执行 catch 中的程序码,而 try 中的程序码一样不会继续执行下去。

async/await 混搭 All 与 Race

一开始有提到 async/awaitPromise 的语法糖,因此 async/await 其实以可以和 Promise.allPromise.race 一同使用,这也算是目前比较常用再处理 Ajax 处理顺序的写法:


const p = new Promise((resolve) => {
  if (true) {
    resolve(`直接执行 Promise`)
  }
})

function PromiseFn(String) {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      if (String.length >= 5) {
        resolve(`Promise 成功, ${String} 共 ${String.length} 个字 `)
      } else {
        reject('Promise 失败')
      }
    }, 2000);
  });
}

async function usePromise() {
	const data1 = await Promise.all([PromiseFn('Ryder'), PromiseFn('youtube')])
	console.log(data1) // ['Promise 成功, Ryder 共 5 个字 ', 'Promise 成功, youtube 共 7 个字 ']
	const data2 = await p
	console.log(data2) // '直接执行 Promise'
}

参考文献


<<:  [DAY-11] 诚实敢言最大化 建立回馈循环

>>:  [Day24]创建Table及捞取资料

端点安全防护 - 防毒软件与软件防火墙

适用人员: 技术人员。 适用法规: 资通安全责任等级分级办法 技术面分类提要 网路架构 端点安全防护...

Day21 Raid原理

Raid可以理解为是将多个硬碟组合在一起,利用虚拟储存技术,形成一个硬碟阵列,用来提升储存空间和制造...

Day 0x 1D - odoo addons 永丰金流开发(Part 4 - Website template, data... more)

*** 模组资料夹 payment_sinopac 以 "/" 来代表此资料夹 ...

Javascript 传值传址&深浅拷贝

前言 因为公司前端资料已经处理成单层结构,所以都没注意到浅拷贝、深拷贝的实际差别。 在读完高手文章後...

30天学会 Python: Day 13-站在巨人的肩上

tags: python, iron_man title: PyDay12 现代的人可以快速得产出...