JavaScript Promises: then(f,f) vs then(f).catch(f)
在 JavaScript 中,我们有两种方式访问 promise 的成功状态值和失败结果:
A) 使用 promise.then(fn, fn)
的两个回调函数:
promise.then(success, error)
B) 或者使用 promise.then(fn).catch(fn)
链式调用:
promise.then(success).catch(error)
这两种相似的方式有什么不同吗?让我们一起寻找!
相同点
让我们考虑我们一直使用的回调函数:
function success(value) {
console.log('Resolved: ', value)
}
function error(err) {
console.log('Error: ', err)
}
success()
函数在成功状态时被调用,自然地 error()
在失败时调用。
在大多数的用例中这两种方式的结果是相似的:如果 promise
的状态为成功,success()
在下面代码中都会被调用:
Promise.resolve('Hi!').then(success, error)
// Logs 'Resolved: Hi!'
Promise.resolve('Hi!').then(success).catch(error)
// Logs 'Resolved: Hi!'
另外,在失败时,error()
被调用:
Promise.reject('Oops!').then(success, error)
// Logs 'Error: Oops!'
Promise.reject('Oops!').then(success).catch(error)
// Logs 'Error: Oops!'
不同点
两者的不同在于在 promise 的成功回调函数 success()
中返回一个失败状态的 promise 时。这种情况可能发生无效的成功状态。
让我们修改成功状态的回调函数使其返回一个失败状态的 promise:
function rejectSuccess(invalidValue) {
console.log('Invalid success: ', invalidValue)
return Promise.reject('Invalid!')
}
现在让我们在下面两种相似代码中使用 rejectSuccess
:
Promise.resolve('Zzz!').then(rejectSuccess, error)
// Logs 'Invalid success: Zzzzz!'
Promise.resolve('Zzz!').then(rejectSuccess).catch(error)
// Logs 'Invalid success: Zzzzz!'
// Logs 'Error: Invalid!'
当 rejectSuccess
返回一个失败状态的 promise 时,Promise.resolve('Zzz!').then(rejectSuccess, error)
仅仅调用了 rejectSuccess
函数。error()
回调函数没有被引用。
Promise.resolve('Zzz!').then(rejectSuccess).catch(error)
调用了 rejectSuccess
是因为 promise 是成功状态的。但是 rejectSuccess
返回一个失败状态的 promise,这个状态被 .catch(error)
捕获导致 error()
回调函数被引用。
可以换个思路考虑, then(rejectSuccess).catch(error)
类似于 then(rejectSuccess),then(null, error)
。
什么时候使用
then(rejectSuccess).catch(error)
是非常有用的,举例来说,当你考虑请求一个列表时,同时必须要考虑最小列表项。
于是,如果该列表是空白的,我们可以简单返回失败状态:
import axios from 'axios'
axios('/list.json')
.then((response) => {
const list = response.data
if (list.length === 0) {
return Promise.reject(new Error('Empty list!'))
}
return list
})
.catch((err) => {
console.log(err)
})
在上面的例子中,.catch(error)
会捕获请求错误和空白列表。
总结
promise.then(success, error)
与 promise.then(success).catch(error)
之间的主要不同在于当 success
回调函数返回失败状态的 promise 时,第二种方式可以捕获失败状态。
本文由 吳文俊 翻译,原文地址 JavaScript Promises: then(f,f) vs then(f).catch(f)