You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 06:07:07