如何在Laravel8+InertiaJS+Vue3项目中捕获服务端请求错误并展示
问题原因
你遇到的onError不触发的核心原因有两个:
- Inertia的form实例的
onError回调仅会在服务端返回符合Inertia协议、携带errors字段的响应时触发,普通JSON响应、仅带with闪存消息的响应都不会触发该回调 - Laravel默认的异常处理没有针对Inertia请求做适配,非验证类的异常不会自动返回带errors的响应格式
解决方案
1. 适配表单验证错误场景(新增广告的422错误)
Laravel的AdFormRequest验证失败时会自动抛出ValidationException,你只需修改app/Exceptions/Handler.php的render方法,针对Inertia请求返回带错误的重定向即可:
public function render($request, Throwable $e) { // 处理Inertia请求的异常 if ($request->inertia()) { // 验证错误场景 if ($e instanceof \Illuminate\Validation\ValidationException) { return redirect()->back() ->withErrors($e->errors()) ->withInput(); } // 其他HTTP异常/业务异常场景 return redirect()->back() ->withErrors(['msg' => config('app.debug') ? $e->getMessage() : '操作失败,请稍后再试']) ->withInput(); } return parent::render($request, $e); }
修改后验证失败的422错误会自动携带errors字段,触发onError回调,你可以在回调里直接取对应字段的错误弹窗,或者统一展示:
onError: (errors) => { console.log(errors) // 统一弹窗展示第一个错误 const firstError = Object.values(errors)[0][0] Swal.fire('操作失败', firstError, 'error') }
如果你的store方法里需要处理广告创建失败的业务错误,不要用back()->with()返回消息,改用back()->withErrors()即可触发onError回调。
2. 适配业务异常场景(删除广告的500错误)
你现在的删除逻辑里捕获异常后返回的是普通JSON响应,Inertia无法识别,你需要改为返回带errors的重定向响应即可:
catch (QueryException $e) { DB::rollBack(); \Log::info( '-1 AdController store $e->getMessage() ::' . print_r( $e->getMessage(), true ) ); // 改为带errors的返回 return back()->withErrors(['msg' => '删除广告失败:'.$e->getMessage()]); }
这个时候抛出的业务错误也会触发onError回调,你可以直接取errors.msg展示弹窗。
3. 额外注意事项
如果你的项目里全局注册了Inertia的error事件监听,请确保没有在全局监听里return false,否则局部的onError回调会被拦截无法触发:
// 错误写法,会拦截局部onError Inertia.on('error', (event) => { console.log(event) return false }) // 正确写法,不拦截局部回调 Inertia.on('error', (event) => { console.log('全局错误', event) })
内容的提问来源于stack exchange,提问作者mstdmstd
相关产品推荐
相关产品推荐

