Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES6 系列之 Async #75

Open
yangtao2o opened this issue Apr 6, 2020 · 0 comments
Open

ES6 系列之 Async #75

yangtao2o opened this issue Apr 6, 2020 · 0 comments

Comments

@yangtao2o
Copy link
Owner

yangtao2o commented Apr 6, 2020

ES6 系列之 Async

ES2017 标准引入了 async 函数,使得异步操作变得更加方便。在异步处理上,async 函数就是 Generator 函数的语法糖。

其实 async 函数的实现原理,就是将 Generator 函数和自动执行器,包装在一个函数里。

async function fn(args) {
  // ...
}

// 等同于
function fn(args) {
  // spawn 函数指的是自动执行器,就比如说 co
  return spawn(function*() {
    // ...
  });
}

使用 async 会比使用 Promise 更优雅的处理异步流程。

  1. 代码更加简洁
function fetch() {
  return (
    fetchData()
    .then(() => {
      return "done"
    });
  )
}

async function fetch() {
  await fetchData()
  return "done"
};
  1. 错误处理
function fetch() {
  try {
    fetchData()
      .then(result => {
        const data = JSON.parse(result);
      })
      .catch(err => {
        console.log(err);
      });
  } catch (err) {
    console.log(err);
  }
}

try/catch 能捕获 fetchData() 中的一些 Promise 构造错误,但是不能捕获 JSON.parse 抛出的异常,如果要处理 JSON.parse 抛出的异常,需要添加 catch 函数重复一遍异常处理的逻辑。

async/await 的出现使得 try/catch 就可以捕获同步和异步的错误。

async function fetch() {
  try {
    const data = JSON.parse(await fetchData());
  } catch (err) {
    console.log(err);
  }
}
  1. 调试

因为 then 中的代码是异步执行,所以当你打断点的时候,代码不会顺序执行。而使用 async 的时候,则可以像调试同步代码一样调试。

问题:给定一个 URL 数组,如何实现接口的继发和并发?

async 继发实现:

// 继发一
async function loadData() {
  var res1 = await fetch(url1);
  var res2 = await fetch(url2);
  var res3 = await fetch(url3);
  return "whew all done";
}
// 继发二
async function loadData(urls) {
  for (const url of urls) {
    const response = await fetch(url);
    console.log(await response.text());
  }
}

async 并发实现:

// 并发一
async function loadData() {
  var res = await Promise.all([fetch(url1), fetch(url2), fetch(url3)]);
  return "whew all done";
}
// 并发二
async function loadData(urls) {
  // 并发读取 url
  const textPromises = urls.map(async url => {
    const response = await fetch(url);
    return response.text();
  });

  // 按次序输出
  for (const textPromise of textPromises) {
    console.log(await textPromise);
  }
}

async 错误捕获:为了简化比较复杂的捕获,我们可以给 await 后的 promise 对象添加 catch 函数:

// to.js
export default function to(promise) {
  return promise
    .then(data => {
      return [null, data];
    })
    .catch(err => [err]);
}
// 使用
[err, user] = await to(UserModel.findById(1));

async 会取代 Generator 吗?

Generator 本来是用作生成器,使用 Generator 处理异步请求只是一个比较 hack 的用法,在异步方面,async 可以取代 Generator,但是 async 和 Generator 两个语法本身是用来解决不同的问题的。

async 会取代 Promise 吗?

  • async 函数返回一个 Promise 对象
  • 面对复杂的异步流程,Promise 提供的 all 和 race 会更加好用
  • Promise 本身是一个对象,所以可以在代码中任意传递
  • async 的支持率还很低,即使有 Babel,编译后也要增加 1000 行左右。

原文链接:ES6 系列之我们来聊聊 Async

@yangtao2o yangtao2o changed the title ES6 系列之我们来聊聊 Async ES6 系列之 Async Apr 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant