javascript - 异步函数中的多个 try-catch 块
问题描述
我有一个异步函数,其中有一些这样的操作:
async function myAsyncFunction(argument) {
let arrayTasks = [
{
const run = async () => {
let response = await getDataAsync();
}
},
{
const run = async () => {
let response = await getDataAsync();
}
}
]
for (const index in arrayTasks) {
await arrayTasks[index].run();
}
}
上面的函数是我的代码的简化版本,它可以工作。但我不确定我需要在哪里放置 try-catch 块:
包装所有内容功能:
async function myAsyncFunction(argument) {
try{
// All code
}catch (e) {
// catch code
}
}
或者在我的 asyncs 函数和 for 运算符中:
async function myAsyncFunction(argument) {
let arrayTasks = [
{
const run = async () => {
try{
let response = await getDataAsync();
}catch (e) {
// catch code
}
}
},
{
const run = async () => {
try{
let response = await getDataAsync();
}catch (e) {
// catch code
}
}
}
]
for (const index in arrayTasks) {
try{
await arrayTasks[index].run();
}catch (e) {
// catch code
}
}
}
什么是正确的方法?该arrayTasks
变量是我原始代码的动态长度。
解决方案
取决于您要处理故障的方式和位置。
“执行可能失败的异步任务数组”的一种方法是这样的模式:
async function myAsyncFunction(argument) {
const success = async res => ({ success: await res }) // Promise<{success: res}>
const error = async err => ({ error: await err }) // Promise<{error: e}>
const arrayTasks = [
{
run: async () => getDataAsync()
}
},
{
run: async () => getDataAsync()
}
]
const runWithResult = task => task.run().then(success).catch(error)
const outcomes = await Promise.all(arrayTasks.map(runWithResult))
console.log(outcomes) // array of {error: e} | {success: res}
}
您可以将.catch()
处理程序链接到函数上,它与将其包装在/async
中具有相同的效果。try
catch
更多在这里,如果你有兴趣。“没有 fp-ts 的重构”部分展示了如何将该数组从 减少[{error: e} | {success: res}]
到{error: [], success: []}
,这更容易使用:
const { error, success } = outcomes.reduce((acc, o) => o.error ?
{ error: [...acc.error, o.error], success: acc.success } :
{ error: acc.error, success: [...acc.success, o.success] },
{ error: [], success: [] })
这是一种称为 FP 类型Either
- 操作可能会返回“任一”(在这种情况下)值或错误。
您的代码不会使用这种方法抛出。
如果您知道某事可能会失败,那并不例外。例外情况是发生一些意外故障,恕我直言。
提前知道的“可能失败的任务”只需要编写错误路径代码即可。
如果您采用这种方法,我建议将其构建为一流的状态缩减机,如下所示:
// Takes an array of async tasks that may throw of shape {run: () => Promise<result>}
// Returns Promise<{error: error[], success: result[]}>
async function executeAsyncTasks(arrayOfAsyncTasks) {
const success = async res => ({ success: await res }) // Promise<{success: res}>
const error = async err => ({ error: await err }) // Promise<{error: e}>
const runWithResult = task => task.run().then(success).catch(error)
const outcomes = await Promise.all(arrayOfAsyncTasks.map(runWithResult))
const outcomesFlat = outcomes.reduce((acc, o) => o.error ?
{ error: [...acc.error, o.error], success: acc.success } :
{ error: acc.error, success: [...acc.success, o.success] },
{ error: [], success: [] })
return outcomesFlat
}
推荐阅读
- graphql - GraphQL 使用来自返回结果集的动态 ID 来呈现正确的数据集
- typescript - 仅将可区分联合类型限制为当前属性
- android - 颤振 | showModalBottomSheet 基于键盘高度的底部填充,但动画很慢
- android - 如何让服务器主动通知客户端资源变化?
- sql - SQL 来识别某些列与过滤器不同的 ID
- android - 有没有办法在明暗模式之间切换后保留变量状态的值以显示在文本视图中
- java - 调用 MediaProjection.createVirtualDisplay 时无法启动已经启动的 MediaProjection 并且很少出现 NullPointerException
- javascript - VueJS 适用于 chrome 但不适用于 Safari
- javascript - 如何使用 JS 在客户端网页中编写通知?
- javascript - 如何使用 JS 获取 html 页面(元素)