为何jQuery AJAX POST请求提交成功却触发错误回调?
问题
我用Laravel 8开发了一个博客应用,正在实现jQuery(v3.5.0)AJAX提交评论及回复的功能。目前评论能成功存入数据库,但AJAX总是执行error回调,弹出错误提示框。查看Network面板,请求先返回302状态码,接着是200状态码。
控制器代码(add_comment方法)
public function add_comment( Request $request ) { $rules = [ 'msg' => 'required' ]; $messages = [ 'msg.required' => 'Please enter a message' ]; $validator = Validator::make( $request->all(), $rules, $messages ); if ( $validator->fails() ) { return redirect()->back() ->withErrors( $validator->errors() ) ->withInput() ->with( 'error', 'Please correct the errors below' ); } $fields = $validator->validated(); $comment = [ 'user_id' => Auth::user()->id, 'article_id' => $request->get( 'article_id' ), 'parent_id' => $request->get( 'parent_id' ), 'body' => $fields['msg'], 'approved' => 0 ]; // Insert comment in the 'comments' table $query = Comment::create( $comment ); if ($query) { return redirect()->back()->with([ 'success' => 'Your comment is pending.', 'success_comment_id' => $request->get('parent_id'), ]); } if (!$query) { return redirect()->back()->with( 'error', 'Adding comment failed' ); } }
评论表单模板
<div class="form-wrapper"> <div class="alert-box-ajax alert-box alert-box--success"> Your comment is pending </div> <div class="alert-box-ajax alert-box alert-box--error"> Failed to add comment! </div> <form class="commentForm" method="post" action="{{ route('comment.submit') }}" autocomplete="off"> @csrf <fieldset> <input type="hidden" name="article_id" value="{{ isset($article->id) ? $article->id : $article_id }}"> <input type="hidden" name="parent_id" value="{{ $comment->id ?? '' }}"> <div class="message form-field"> <textarea name="msg" id="message" class="h-full-width" placeholder="Your Message" required></textarea> @error('msg') <p class="help-block text-danger">{{ $message }}</p> @enderror </div> <br> <input name="submit" id="submit" class="btn btn--primary btn-wide btn--large h-full-width" value="Add Comment" type="submit"> </fieldset> </form> </div>
AJAX脚本
$(".commentForm").each(function () { var form = $(this); form.validate({ errorElement: "p", errorClass: "help-block text-danger", submitHandler: function (_form, event) { event.preventDefault(); var $fields = form.find("textarea"), url = form.attr("action"), data = form.serialize(); $.ajax({ dataType: "json", type: "post", url: url, data: data, cache: false, success: function () { form.closest(".form-wrapper").find(".alert-box--success").slideDown(250).delay(2500).slideUp(250) .slideDown(250) .delay(2500) .slideUp(250); $fields.val(""); }, error: function () { form.closest(".form-wrapper").find(".alert-box--error").slideDown(250).delay(2500).slideUp(250) .slideDown(250) .delay(2500) .slideUp(250); }, }); }, }); });
解决方案
问题核心在于Laravel控制器返回重定向响应,而AJAX请求预期JSON格式。你的add_comment方法无论成功还是失败都返回redirect()->back(),这会给AJAX请求返回302状态码。虽然浏览器会自动跟随重定向到200状态的页面,但jQuery的AJAX因为无法解析重定向后的HTML内容(预期是JSON),所以触发了error回调。
1. 修改控制器,针对AJAX请求返回JSON
调整add_comment方法,判断请求是否为AJAX类型,返回对应的JSON响应而非重定向:
public function add_comment(Request $request) { $rules = [ 'msg' => 'required' ]; $messages = [ 'msg.required' => 'Please enter a message' ]; $validator = Validator::make($request->all(), $rules, $messages); if ($validator->fails()) { // AJAX请求返回JSON错误 if ($request->wantsJson()) { return response()->json([ 'status' => 'error', 'message' => 'Please correct the errors below', 'errors' => $validator->errors() ], 422); } return redirect()->back() ->withErrors($validator->errors()) ->withInput() ->with('error', 'Please correct the errors below'); } $fields = $validator->validated(); $comment = [ 'user_id' => Auth::user()->id, 'article_id' => $request->get('article_id'), 'parent_id' => $request->get('parent_id'), 'body' => $fields['msg'], 'approved' => 0 ]; $query = Comment::create($comment); if ($query) { // AJAX请求返回成功JSON if ($request->wantsJson()) { return response()->json([ 'status' => 'success', 'message' => 'Your comment is pending.', 'success_comment_id' => $request->get('parent_id') ]); } return redirect()->back()->with([ 'success' => 'Your comment is pending.', 'success_comment_id' => $request->get('parent_id'), ]); } // 失败时的AJAX响应 if ($request->wantsJson()) { return response()->json([ 'status' => 'error', 'message' => 'Adding comment failed' ], 500); } return redirect()->back()->with('error', 'Adding comment failed'); }
2. 调整前端AJAX脚本,处理JSON响应
修改JS代码,根据返回的JSON状态显示对应提示,同时处理验证错误:
$(".commentForm").each(function () { var form = $(this); form.validate({ errorElement: "p", errorClass: "help-block text-danger", submitHandler: function (_form, event) { event.preventDefault(); var $fields = form.find("textarea"), url = form.attr("action"), data = form.serialize(); // 先隐藏所有提示框 form.closest(".form-wrapper").find(".alert-box-ajax").slideUp(250); $.ajax({ dataType: "json", type: "post", url: url, data: data, cache: false, success: function (response) { // 显示成功提示 form.closest(".form-wrapper").find(".alert-box--success") .slideDown(250) .delay(2500) .slideUp(250); $fields.val(""); // 可选:在这里动态渲染新评论到页面 }, error: function (xhr) { var $errorBox = form.closest(".form-wrapper").find(".alert-box--error"); // 处理验证错误(422状态码) if (xhr.status === 422) { var errors = xhr.responseJSON.errors; $errorBox.text(errors.msg[0]).slideDown(250).delay(2500).slideUp(250); } else { // 其他错误显示默认提示 $errorBox.slideDown(250).delay(2500).slideUp(250); } }, }); }, }); });
3. 隐藏默认提示框
给提示框添加初始隐藏的CSS样式:
.alert-box-ajax { display: none; }
修改完成后,AJAX请求会正确接收JSON响应,成功时触发success回调,失败或验证错误时触发error回调并显示对应信息,不会再出现误判情况。
内容的提问来源于stack exchange,提问作者Razvan Zamfir
相关产品推荐
相关产品推荐

