首先来看下finally在Promise的作用,
finally 会在 then 和 catch 之后执行,无论 then 和 catch 中是否抛出异常
相信这个都比较清楚,下面我来说说我在开发中遇到的bug。
代码大概如下
<!-- 保存按钮防抖 -->
const [loading,setLoading] = useState(false)
<!-- 保存操作 -->
const save = (cb) => {
setLoading(true)
request('/save', {
...params
}).then(() => {
if (cb) {
cb()
} else {
message.success('保存成功')
}
}).finally(() => {
setLoading(false)
})
}
<!-- 第一种情况 无callback直接执行保存操作 -->
save()
<!-- 第二种情况 有callback,且此callback中有另一个异步请求操作 -->
save(() => {
request('/saveConfirm').then(() => {
message.success('保存成功')
})
})
这代代码的大概场景就是在若有cb的情况下,需要等待cb的异步请求执行完后,再把保存操作的按钮loading设置为false,防止用户再次点击。
而问题就出现在防抖失效了,经过调试发现,finally中的setLoading(false)已经提前执行,并没有等待then中的异步请求完成才执行,导致防抖失效。
总结
finally 在 then 或 catch 的同步操作完成后会立即执行, 然而finally 并不会等待 then 或 catch 内部的异步操作完成,除非这些异步操作的结果被返回并传递给下一个 Promise 链。
const save = (cb) => {
setLoading(true)
request('/save', {
...params
}).then(() => {
if (cb) {
// 返回新的Promise对象
return new Promise((resolve) => {
cb(resolve)
})
} else {
message.success('保存成功')
}
}).finally(() => {
setLoading(false)
})
}
save((resolve) => {
request('/saveConfirm').then(() => {
message.success('保存成功')
resolve(null)
})
})