「这是我参与2022首次更文挑战的第23天,活动详情查看:2022首次更文挑战」。
什么是回调地狱
当一个函数作为参数在方法中调用时,这个函数就叫做叫做回调函数,如果在回调函数中再传入一个函数,层层嵌套回调,这样就会形成回调地狱
回调地狱是一种不好的编码习惯,可读性差并且难以维护,比如下面的代码
const process = (msg, cb) => {
setTimeout(() => {
console.log(msg)
cb()
}, 1000)
}
process('msg 1', () => {
process('msg 2', () => {
process('msg 3', () => {
process('msg 4', () => {
console.log('end')
})
})
})
})
如何解决回调地狱
解决回调地狱的思路就是要把一层层嵌套的回调函数“解救”出来,把多层的结构给他“拍平”
Thunk函数
还不知道什么是Thunk函数 阮一峰 Thunk 函数的含义和用法
Thunk函数是一个比较“古老”的概念,上个世纪60年代就诞生了,在Javascript中其实是结合柯里化的一种应用,可以将多参数版本的函数转换为单参数,并且在返回的新函数中只接受回调函数作为参数。
- 将上面的例子修改,利用Thunk函数加上一个执行函数就可以从回调地狱中解救出来,只需要维护执行顺序的数组即可
const process = (msg, cb) => {
setTimeout(() => {
console.log(msg)
cb && cb()
}, 1000)
}
// thunk函数
const thunk = (msg) => (cb) => process(msg, cb)
const p1 = thunk('msg 1')
const p2 = thunk('msg 2')
const p3 = thunk('msg 3')
const p4 = thunk('msg 4')
// 执行顺序
const arr = [p1, p2, p3, p4]
// 执行函数
const gen = (arr) => () => arr.reduceRight((a, b) => () => b(() => a()))()
const run = gen(arr)
run()
Promise
采用链式操作,按照顺序调用,在 then 中,会等待前一个 Promise 的状态变成 Fulfilled 再执行,返回的也是一个 Promise 对象
- 将之前的例子用
Promise包一层,可以看到改用链式调用会非常之优雅
const process = (msg, cb) => {
setTimeout(() => {
console.log(msg)
cb && cb()
}, 1000)
}
const processPromise = msg => {
return new Promise((resolve, reject) => {
process(msg, resolve)
})
}
processPromise('msg 1')
.then(_ => processPromise('msg 2'))
.then(_ => processPromise('msg 3'))
.then(_ => processPromise('msg 4'))
async/await
async/await 是 Promise 的一种语法糖,会默认的返回一个 Promise 对象 resolve 的值,可以直接进行 then 操作,可以将 Promise 的链式操作改为顺序执行(异步等待)
const run = async() => {
await processPromise('msg 1')
await processPromise('msg 2')
await processPromise('msg 3')
await processPromise('msg 4')
}
run()