开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第30天,点击查看活动详情
🎈大家好,我是
李乐一,新人初来乍到,请多多关照~📝小小的前端一枚,分享一些日常的学习和项目实战总结~
😜如果本文对你有帮助的话,帮忙点点赞呀!ღ( ´・ᴗ・` )比心~
写在前面
我们常用的实现异步的方法有很多,比如Promise等,本文主要记录一下async,await的实现。温故而知新。
JavaScript 异步编程
JavaScript 是单线程,支持异步编程才能提高运行效率。异步编程的语法是让异步过程写起来更像同步过程。
1. 回调函数
回调函数,就是把任务的第二段放在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数。
📝举个栗子
const fs = require('fs')
fs.readFile('', (err, data) => {
if (err) {
console.error(err)
return
}
console.log(data.toString())
})
回调函数最大的问题是容易形成回调地狱,也就是多个回调函数嵌套,降低代码可读性,增加逻辑的复杂性
📝举个栗子
fs.readFile(fileA, function (err, data) {
fs.readFile(fileB, function (err, data) {
// ...
})
})
2. Promise
为解决回调函数的不足,出现了新的语法 Promise。
📝举个栗子
const fs = require('fs')
const readFileWithPromise = file => {
return new Promise((resolve, reject) => {
fs.readFile(file, (err, data) => {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
}
readFileWithPromise('')
.then(data => {
console.log(data.toString())
return readFileWithPromise('/etc/profile')
})
.then(data => {
console.log(data.toString())
})
.catch(err => {
console.log(err)
})
Promise 的工作原理是将回调函数的横向加载变成纵向加载,达到链式调用的效果,避免了回调地狱的出现。其最大问题是代码冗余,增加了大量的
then操作,原来的语义变得很不清楚。
3. async、await
为了更好的实现异步功能,出现了async、await
📝举个栗子
const fs = require('fs')
async function readFile() {
try {
var f1 = await readFileWithPromise('')
console.log(f1.toString())
var f2 = await readFileWithPromise('')
console.log(f2.toString())
} catch (err) {
console.log(err)
}
}
async、await 函数写起来跟同步函数一样,接收 Promise 或原始类型的值。
async、await
1. generator
generator 函数是协程在 ES6 的实现。协程简单来说就是多个线程互相协作,完成异步任务。
整个 generator 函数就是一个封装的异步任务,异步操作需要暂停的地方,都用 yield 语句注明。generator 函数的执行方法如下:
📝举个栗子
function* gen(x) {
console.log('start')
const y = yield x * 2
return y
}
const g = gen(1)
g.next() // start { value: 2, done: false }
g.next(4) // { value: 4, done: true }
gen()不会立即执行,而是一上来就暂停,返回一个Iterator对象- 每次
g.next()都会打破暂停状态去执行,直到遇到下一个yield或者return - 遇到
yield时,会执行yield后面的表达式,并返回执行之后的值,然后再次进入暂停状态,此时done: false。 next函数可以接受参数,作为上个阶段异步任务的返回结果,被函数体内的变量接收- 遇到
return时,会返回值,执行结束,即done: true - 每次
g.next()的返回值永远都是{value: ... , done: ...}的形式
2. async、await
async、await 可以看作自带启动器的 generator 函数的语法糖。不同的是,async、await 只支持 Promise 和原始类型的值,不支持 thunk 函数。
📝举个栗子
async function readfile() {
try {
const content1 = await readFileWithPromise('', 'utf8')
console.log(content1)
const content2 = await readFileWithPromise('e', 'utf8')
console.log(content2)
return 'done'
} catch (err) {
throw(err)
}
}
readfile().then(
res => console.log(res),
err => console.error(err)
)