js是单线程的,前端的并发指的是:在极短时间内发送多个数据请求,比如说循环中发送ajax

总结:推荐使用 axios来发送 ajax请求

  • 支持 node环境和浏览器环境
  • 提供支持并发的api,如axios.all、axios.spread
  • 这些api考虑到的边界条件、兼容性肯定是比原生方法好用的
  • 如果用原生的 Promise,推荐使用:Promise.allSettled

async & await

async函数其实就是generator + promise的语法糖
koa2 可以在node环境中使用async、await语法,所以在koa2中很推崇使用async、await来处理异步

  1. const getData1 = () =>
  2. new Promise((resolve, reject) => {
  3. setTimeout(() => resolve([1, 2, 3]), 1000);
  4. });
  5. const getData2 = () =>
  6. new Promise((resolve, reject) => {
  7. setTimeout(() => resolve([4, 5, 6]), 2000);
  8. });
  9. const useAsync = async () => {
  10. console.time(); // 开始计时
  11. // 直接 await会阻塞队列,总的执行时间是两个请求加起来的时间;最终能拿到两个异步的值,看下面的优化
  12. // const data1 = await getData1(); // 直接 await会阻塞
  13. // const data2 = await getData2();
  14. // console.timeEnd(); // default: 3008.10400390625 ms
  15. // await优化,**一行代码判断是否掌握 async的原理**
  16. const p1 = getData1();
  17. const p2 = getData2();
  18. // 处理并发不阻塞的 await语法
  19. const data1 = await p1;
  20. const data2 = await p2;
  21. console.timeEnd(); // default: 2008.10400390625 ms
  22. console.log(data1, data2); // (3) [1, 2, 3] (3) [4, 5, 6]
  23. }
  24. useAsync();

Promise.all

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Promise的特点

  • Promise构造函数是同步的,promise.then()中的函数是异步的
  • Promise只能从pending->resolve 或pending->reject,状态一但改变就不能再变
  • Promise.then、Promise.catch中不能return promise对象本身
  • Promise.then中必须是函数

用Promise.all处理并发:

  • 当所有promise全部成功时, 会走.then,并且可以拿到所有promise中传进resolve中的值
  • 其中有一个promise执行失败, 不会走.then, 会走finally,finally不管成功失败都会执行
    • 如果其中有一个 Promise走Preject,不能获取到其它 resolve的传递过来的值
  • 因为finally回调函数中,无参数,所有拿不到执行成功的promise传进resolve的值
    1. console.time(); // 开始计时
    2. Promise.all([p1, p2])
    3. .then(result => {
    4. // 有一个请求失败,不会执行到这里,直接走 finally
    5. console.timeEnd();
    6. console.log(result);
    7. })
    8. .finally(() => {
    9. console.timeEnd(); // 计时结束 default: 3000.71923828125 ms
    10. })

Promise.allSettled

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled

Promise.allSettled在处理并发时,不怕异步执行失败,继续会走.then

  • 其中有一个promise执行失败时,会继续走.then, 并且可以同时拿到传给resolve、reject的值
  • 完美解决promise.all在并发有失败情况下,拿不到值的情况
    1. console.time(); // 开始计时
    2. Promise.allSettled([p1, p2])
    3. .then(result => {
    4. console.timeEnd();
    5. console.log(result); // [{…}, {…}]
    6. /* status可以拿到promis执行状态, value、reason 分别可以拿到执行成功和执行失败传过去的值
    7. 0: {status: "fulfilled", value: Array(1)}
    8. 1: {status: "rejected", reason: Array(1)}
    9. */
    10. })

缺点,比起promise.all兼容性差一点,多了两个不支持的浏览器
安卓端火狐浏览器 Firefox for Android
Samsung Internet 浏览器