AsyncFunction学习笔记

异步解决方案 AsyncFunction 学习笔记。

webpack

未使用到的变量和函数,不会出现到编译后的文件里。(tree shaking)

Babel

关于babel如何编译async函数的记录

只有@babel/preset-env

编译成功,会将async函数编译为Promise,但同时会报错regeneratorRuntime is undefined

函数无法运行。

再含有@babel/plugin-transfrom-runtime

编译失败,会提示缺少@babel/runtime/helpers/asyncToGenerator@babel/runtime/regenerator

再含有@babel/runtime

此依赖需要安装为项目依赖。

1
$ yarn add @babel/runtime

编译成功,且函数运行成功。

@babel/polyfill的使用

安装

1
$ yarn add @babel/polyfill

全部引入

可以直接在项目入口导入,或者在webpack的entry中。

1
2
3
4
5
// webpack.config.js

module.exports = {
entry: ['@babel/polyfill', `${__dirname}/src/main.js`]
}

非webpack全部引入

在js文件顶部使用require或者import引入

1
2
3
4
5
6
7
8
// main.js
import '@babel/polyfill'

// or

require('@babel/polyfill')

// other code

配置.babelrc,将@babel/preset-nevuseBuiltIns字段设置为entry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// .babelrc.js

module.exports = {
presets: [
['@babel/preset-env', {
targets: {
node: true, // config your env
esModules: true
}
modules: 'auto',
useBuiltIns: 'entry'
}]
]
}

按需引入

无需引入@babel/polyfill,但仍需安装

1
2
3
4
5
6
7
8
9
10
// .babelrc.js

module.exports = {
presets: [
['@babel/preset-env', {
modules: false,
useBuiltIns: 'usage'
}]
]
}

Async

async function声明用于定义一个返回AsyncFunction对象的异步函数

异步函数指通过事件循环异步执行的函数,它会通过一个隐式的Promise返回其结果。

这个异步函数的语法和结构像是标准的同步函数。

async/await可用于简化多个promise异步调用的操作。

基础用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function resolveAfter2Seconds () {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved!')
}, 2e3);
})
}

async function asyncCall () {
console.log('Calling start')
const result = await resolveAfter2Seconds()
console.log(result)
console.log('Calling end')

// 以下2种操作会被catch捕获
// throw new Error('async throw error')
// console.log(notExistVar)

return 'This string returned by async function'
}

asyncCall()
.then(str => {
console.log(str)
})
.catch(err => {
consoe.log(err)
})
/*
output
-> Calling start
2s later
-> resolved!
-> Calling end
-> This string returned by async function
*/
  • 使用async function声明来定义一个AsyncFunction
  • 使用await关键字来处理异步函数,将会使此AsyncFunction暂停执行,等待Promise的结果出来,再恢复AsyncFunction的执行。
  • AsyncFunction中使用return关键字返回的值,会被隐式的Promise进行resolve
  • AsyncFunction中使用throw关键字抛出的错误或者调用该函数时内部的错误,会被隐式的Promise进行reject

await关键字只能在AsyncFunction内部使用,否则会报错SyntaxError

Promise VS Async/Await

MDN示例

AsyncFunction改写Promise链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function getProcessedData (url) {
return donwloadData(url)
.then(v => {
return processDataInWorker(v)
})
.catch(err => {
console.log(err)
return downloadFallbackData(url)
})
}

async function getProcessedData (url) {
let v

try {
v = await donwloadData(url)
} catch (err) {
console.log(err)
v = await downloadFallbackData(url)
}

return processDataInWorker(v)
}

浏览器兼容性

MDN - BCD

Can I Use

  • 非IE浏览器/QQ浏览器
  • 其他高版本浏览器

需要babel来提供回退到 Promise + Promise Polyfill

参考资料

MDN - async function

有钱,任性!!!