异步函数和毁掉函数是 JS 单线程并行模型的核心。

在 JS 中,需要区分 I/O 操作CPU 密集型操作 。针对 I/O 来说,例如网络请求和文件操作,需要程序等待数据准备好后再进行下一步操作,与此同时,程序可以执行其他的代码,这并不会对程序产生阻塞。

而对于 CPU 密集型的操作来说,它会造成线程的阻塞。

  • 对于 I/O 操作来说,我们需要使用 promise , eventscallback 来对请求做划分(schedule)
  • 对于 CPU 密集型的操作来说,它会不可避免的阻塞程序的执行,这时候可以使用 worker threads/web workers 来执行

在使用 ascyn/await 的时候需要注意,未经处理的 promise 将会造成很大的内存使用。

注意事项

  • 不要使用 return await 语句

return await 的问题

通常在函数中, return 语句表明了函数的结束,并且会从当前调用栈中弹出。对于 async 函数来讲,会将一个值用一个已解决(resolved)的 promise 进行包裹,然后再进行返回。

与此同时, await 语句标明 async 函数暂停执行,直到一个给定的 promise 解决之后。将 returnawait 进行结合之后会导致多余的对已经解决的 promise 进行多余的包装和解包装的操作。

通常来说,在 async 函数中最后的 promise 应该被直接返回。

  1. async function saveJSON(output) {
  2. const response = await fetch('https://api.github.com')
  3. const json = await response.json()
  4. const text = JSON.stringify(json)
  5. return fs.readFile(output, text)
  6. }

避免对 async 函数的滥用:

  1. import { promises as fs } from 'fs';
  2. // This is a not-so-efficient wrapper for the native file reader.
  3. async function readFile(filename) {
  4. const contents = await fs.readFile(filename, { encoding: 'utf8' });
  5. return contents;
  6. }
  7. // Preferred
  8. // This optimization avoids the `async` wrapper overhead.
  9. function readFile(filename) {
  10. return fs.readFile(filename, { encoding: 'utf8' });
  11. }