这种情况有多常见?
function writeTransactionsToFile(transactions) { let writeStatus; try { fs.writeFileSync('transactions.txt', transactions); writeStatus = 'success'; } catch (error) { writeStatus = 'error'; } // do something with writeStatus...}
这是另一个我们想要一个取决于是否存在异常的值的实例。
通常, 我们可能会在 try-catch 的范围之外创建一个可变变量,以便在其中和之后无错误地访问。
但情况并非总是这样。只要有一个函数式的 try-catch 就不会这样。
一个纯粹的 tryCatch() 函数避免了可变变量,并在我们的代码库中鼓励可维护性和可预测性。
没有修改外部状态 - tryCatch() 封装了整个错误处理逻辑并产生单一输出。
我们的 catch 变成了一个不需要大括号的单行代码:
function writeTransactionsToFile(transactions) { // 我们现在可以使用 const 了 const writeStatus = tryCatch({ tryFn: () => { fs.writeFileSync('transactions.txt', transactions); return 'success'; }, catchFn: (error) => 'error' }); // do something with writeStatus...}
那么,这个 tryCatch() 函数究竟是什么样子的呢?
从我们以上的使用方式,你已经可以猜到定义了:
function tryCatch({ tryFn, catchFn }) { try { return tryFn(); } catch (error) { return catchFn(error); }}
为了正确地讲述函数的作用,我们确保使用对象参数来明确参数名称——即使只有两个属性。
因为编程不仅仅是达到目的的手段 - 我们还在讲述从开始到结束的代码库中的对象和数据的故事。
TypeScript 在这样的情况下非常好用;我们看看一个泛型类型的 tryCatch() 可能是什么样子:
type TryCatchProps<T> = { tryFn: () => T; catchFn: (error: any) => T;};function tryCatch<T>({ tryFn, catchFn }: TryCatchProps<T>): T { try { return tryFn(); } catch (error) { return catchFn(error); }}
我们用 TypeScript 重写功能性 writeTransactionsToFile() :
function writeTransactionsToFile(transactions: string) { // 返回 'success' 或 'error' const writeStatus = tryCatch<'success' | 'error'>({ tryFn: () => { fs.writeFileSync('transaction.txt', transactions); return 'success'; }, catchFn: (error) => return 'error'; }); // do something with writeStatus...}
我们使用 'success' | 'error' 联合类型来限制我们可以从 try 和 catch 回调中返回的字符串。
不,我们完全不需要担心这个问题 - 如果 tryFn 或 catchFn 是 async ,那么 writeTransactionToFile() 会自动返回一个 Promise 。
这是我们大多数人应该熟悉的另一个 try-catch 情况:发出网络请求并处理错误。
在这里,我们根据请求是否成功来设置一个外部变量(在try-catch 之外)——在 React 应用中,我们可以轻松地用它设置状态。
显然,在真实世界的应用程序中,请求将会是异步的,以避免阻塞用户界面线程:
async function comment(comment: string) { type Status = 'error' | 'success'; let commentStatus: Status; try { const response = await fetch('https://api.mywebsite.com/comments', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ comment }), }); if (!response.ok) { commentStatus = 'error'; } else { commentStatus = 'success'; } } catch (error) { commentStatus = 'error'; } // do something with commentStatus...}
我们再次需要在这里创建一个可变变量,以便它可以进入 try-catch 并且没有作用域错误地成功出来。
我们像以前一样进行重构,这次,我们 async 了 try 和 catch 函数,从而 await 了 tryCatch() :
async function comment(comment: string) { type Status = 'error' | 'success'; // ⚠️ await because this returns Promise<Status> const commentStatus = await tryCatch<Status>({ tryFn: async () => { const response = await fetch('https://api.mywebsite.com/comments', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ comment }), }); // ⚠️ functional conditional return response.ok ? 'success' : 'error'; }, catchFn: async (error) => 'error', }); // do something with commentStatus...}
处理异常时遵循的两个 try-catch 经验法则:
他们将使你的代码在短期和长期内更易于阅读和维护。看看这里的 processJSONFile()
本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-96430-0.html函数式 try-catch 如何转变 JavaScript 代码
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com