如何统一捕获Vue-Concurrency所有Task错误触发弹窗通知?
Vue Concurrency 全局Task错误自动触发Quasar通知实现方案
不需要给每个yield语句单独绑定catch,也不需要依赖不支持链式调用的useTaskGroup,Vue Concurrency本身提供了成熟的事件机制,可以用两种低侵入方案实现全量任务的错误自动提示。
方案1:二次封装useTask组合式函数(最推荐,灵活可控)
对原生useTask做一层轻量封装,统一在封装层监听任务实例的错误事件,自动触发通知。业务代码只需要替换useTask的导入源,原有任务逻辑完全不需要改动。
首先新建封装的组合式函数文件,例如src/composables/useNotifyTask.ts:
import { useTask, type UseTaskOptions, type Task } from 'vue-concurrency'; import { useQuasar } from 'quasar'; export function useNotifyTask<T extends (...args: any[]) => any>( generatorFn: T, options?: UseTaskOptions ): Task<T> { const $q = useQuasar(); // 调用原生方法创建任务实例 const task = useTask(generatorFn, options); // 监听任务错误事件,抛出错误时自动触发通知 task.on('error', (err) => { // 可在此处扩展自定义逻辑:错误过滤、错误码映射、特殊场景跳转等 const errorMsg = err instanceof Error ? err.message : '请求异常,请稍后重试'; $q.notify(errorMsg); }); return task; }
业务代码中替换导入即可,所有冗余的yield后catch可以全部删除:
<script setup lang="ts"> import { timeout } from 'vue-concurrency'; // 替换原vue-concurrency的useTask导入 import { useNotifyTask } from 'src/composables/useNotifyTask'; const exampleAsyncWithError = async () => { await timeout(1); throw new Error('Ruh oh! Error.'); }; // 所有任务直接使用封装后的方法创建,错误自动弹窗 const example1Task = useNotifyTask(function* () { yield exampleAsyncWithError(); yield exampleAsyncWithError(); yield exampleAsyncWithError(); }); const example2Task = useNotifyTask(function* () { yield exampleAsyncWithError(); yield exampleAsyncWithError(); }); const example3Task = useNotifyTask(function* () { yield exampleAsyncWithError(); yield exampleAsyncWithError(); }); </script> <template> <q-btn label="Run Task" @click="example1Task.perform" /> <q-btn label="Run Task" @click="example2Task.perform" /> <q-btn label="Run Task" @click="example3Task.perform" /> </template>
该方案的优势:
- 改造成本极低,仅需替换导入源,存量任务无需修改内部逻辑
- 灵活度高,可在封装层统一实现错误过滤、格式化、特殊错误分支处理
- 不侵入任务原有逻辑,任务实例的
error、isError等状态正常更新,不影响页面其他错误态展示
方案2:全局插件配置(适合无差异化处理的场景)
如果所有任务的错误提示逻辑完全统一,可以在Vue Concurrency初始化时传入全局任务配置,给所有任务默认绑定错误监听,无需额外封装。
在Quasar的boot启动文件中配置插件:
// src/boot/vue-concurrency.ts import { boot } from 'quasar/wrappers'; import VueConcurrency from 'vue-concurrency'; export default boot(({ app, $q }) => { app.use(VueConcurrency, { task: { on: { error: (err) => { const errorMsg = err instanceof Error ? err.message : '请求异常,请稍后重试'; $q.notify(errorMsg); } } } }); });
该方案默认对所有useTask创建的任务生效,如果个别任务不需要弹窗提示,可以在创建任务时单独传入配置覆盖,或在全局错误回调中加标记位过滤特殊错误。
补充:useTaskGroup的错误监听方式
useTaskGroup返回的是任务组实例而非Promise实例,本身不支持then/catch链式调用,但同样可以通过on('error')事件监听组内所有任务的错误,适合临时给一组批量任务绑定提示的场景:
import { useTaskGroup } from 'vue-concurrency'; const taskGroup = useTaskGroup([example1Task, example2Task, example3Task]); taskGroup.on('error', (err) => { $q.notify(err.message); });
内容的提问来源于stack exchange,提问作者TinyTiger
相关产品推荐
相关产品推荐

