Javascript 如何防止ajax post请求提交两次?
我有一个按钮subscribe,它应该通过ajax向我的控制器提交post请求,以便插入到我的表中 这就是我的观点:Javascript 如何防止ajax post请求提交两次?,javascript,jquery,ajax,laravel,Javascript,Jquery,Ajax,Laravel,我有一个按钮subscribe,它应该通过ajax向我的控制器提交post请求,以便插入到我的表中 这就是我的观点: @extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-8"> <div c
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8">
<div class="flash-message"></div>
<div class="card">
<div class="card-header">
<div class="level">
<span class="flex"><a href="{{route('profile',$thread->creator->name)}}">{{$thread->creator->name}}</a> posted:
{{$thread->title}}
</span>
@if(auth()->check())
@if($subscription)
<button class="btn btn-secondary" id="unsubscribe">Unsubscribe</button>
@else
<button class="btn btn-danger" id="subscribe">Subscribe</button>
@endif
@endif
@can('update',$thread)
<a href="{{$thread->path()}}/edit" class="btn btn-link">Edit Thread</a>
<form action="{{$thread->path()}}" method="POST">
@csrf
@method('delete')
<button class="btn btn-link" type="submit">Delete Thread</button>
</form>
@endcan
</div>
</div>
<div class="card-body">
{{$thread->body}}
</div>
</div>
..............
@extends('layouts.app'))
@节(“内容”)
张贴:
{{$thread->title}
@如果(auth()->check())
@if(订阅费)
退订
@否则
订阅
@恩迪夫
@恩迪夫
@can('update',$thread)
@csrf
@方法('delete')
删除线程
@恩德坎
{{$thread->body}
..............
我的应用程序刀片:
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<!--jQuery/share.js -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=" crossorigin="anonymous"></script>
<script src="{{ asset('js/share.js') }}"></script>
<!-- Fonts -->
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<style>
body{
padding-bottom:100px;
}
.level{
display: flex;
align-items: center;
}
.flex{
flex: 1;
}
</style>
</head>
<body>
<div id="app">
@include('layouts.nav')
<main class="py-4">
@yield('content')
</main>
<flash message="{{session('flash')}}"></flash>
</div>
</body>
<style>
.btn-width{
min-width: 70px;
}
</style>
</html>
{{config('app.name','Laravel')}
身体{
填充底部:100px;
}
.级别{
显示器:flex;
对齐项目:居中;
}
.flex{
弹性:1;
}
@包括('layouts.nav')
@产量(‘含量’)
.btn宽度{
最小宽度:70px;
}
调用按钮的代码:
<script type="application/javascript">
$(document).ready(function(){
$('#subscribe').click(function(e){
e.preventDefault();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: "{{route('subscription.store')}}",
method:'POST',
data: {
thread_id: "{{$thread->id}}",
},
success:function(response){
$('div.flash-message').html(response);
},
error:function(error){
console.log(error);
}
});
});
});
$(文档).ready(函数(){
$(“#订阅”)。单击(函数(e){
e、 预防默认值();
$.ajaxSetup({
标题:{
'X-CSRF-TOKEN':$('meta[name=“CSRF-TOKEN”]).attr('content'))
}
});
$.ajax({
url:“{route('subscription.store')}}”,
方法:'POST',
数据:{
线程id:“{{$thread->id}}”,
},
成功:功能(响应){
$('div.flash-message').html(响应);
},
错误:函数(错误){
console.log(错误);
}
});
});
});
据我所知,没有其他元素与我的按钮共享相同的id。而且,我的按钮不是表单提交,所以不应该调用两次。检查开发工具不会显示任何错误,在“网络”选项卡中,使用同一启动器相同地调用两个请求。
所以,我有点想知道为什么会发生这种情况。ajax post请求不应该只提交一次请求吗
我真的很想弄清这一点,因为大多数其他类似的问题都会调用submit两次,而我的代码应该只调用它一次。相反,它对我的数据库进行了两次插入
我还可以做些什么来找出问题的根本原因?您正在调用函数两次,一次在document ready中,另一次在按钮上单击remover document您是否尝试过返回false?像这样:
$(document).ready(function(){
let subscribeClick = function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: "{{route('subscription.store')}}",
method:'POST',
data: {
thread_id: "{{$thread->id}}",
},
success:function(response){
$('div.flash-message').html(response);
},
error:function(error){
console.log(error);
}
});
return false;
}
$('#subscribe').click(function(e){
e.preventDefault();
e.stopImmediatePropagation();
subscribeClick();
});
});
您的javascript是否可能被加载了两次?这将附加两个相同的侦听器,并在一次单击中发送两次请求。如果在事件处理程序中放置一个console.log,是否也会看到两次 另外,显然,
。单击
会为与传递给jQuery对象的选择器相匹配的每个元素添加一个单独的事件侦听器。如果你这样做会发生什么
$(文档).ready(函数(){
$(“#订阅”)。在(“单击”上,函数(e){
e、 预防默认值();
$.ajaxSetup({
标题:{
“X-CSRF-TOKEN”:$('meta[name=“CSRF TOKEN”]”)attr(“内容”),
},
});
$.ajax({
url:“{route('subscription.store')}}”,
方法:“张贴”,
数据:{
线程id:“{{$thread->id}}”,
},
成功:功能(响应){
$(“div.flash-message”).html(响应);
},
错误:函数(错误){
console.log(错误);
},
});
});
});
您可以尝试以下选项:
(1) 在ajax调用中使用async:false
,停止其他代码的执行,直到收到当前ajax调用的响应为止
$('#subscribe').click(function(e) {
e.preventDefault();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: "{{route('subscription.store')}}",
method: 'POST',
async: false,
data: {
thread_id: "{{$thread->id}}",
},
success: function(response) {
$('div.flash-message').html(response);
},
error: function(error) {
console.log(error);
}
});
});
或
(2) 您可以使用事件接口的stopPropagation()
方法来防止当前事件在捕获和冒泡阶段进一步传播
$('#subscribe').click(function(e) {
e.preventDefault();
e.stopPropagation();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: "{{route('subscription.store')}}",
method: 'POST',
async: false,
data: {
thread_id: "{{$thread->id}}",
},
success: function(response) {
$('div.flash-message').html(response);
},
error: function(error) {
console.log(error);
}
});
});
或
(3) 使用存储请求状态的变量
var isLoading = false;
$(document).ready(function() {
$('#subscribe').click(function(e) {
if (!isLoading ) {
isLoading = true; //make true when request starts
e.preventDefault();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: "{{route('subscription.store')}}",
method: 'POST',
data: {
thread_id: "{{$thread->id}}",
},
success: function(response) {
$('div.flash-message').html(response);
isLoading = false; //make false when response is received
},
error: function(error) {
console.log(error);
isLoading = false; //make false when error is received
}
});
}
});
});
如果我在事件preventDefault之后添加stopImmediatePropagation,那么它就可以工作了。但是,我只是想了解问题的原因,因为它在默认情况下应该工作。-preventDefault:如果事件可取消,则取消事件,而不停止事件的进一步传播。-停止传播:阻止当前事件的进一步传播。-stopImmediatePropagation:防止调用同一事件的其他侦听器。您知道为什么会发生这种情况吗?我使用了很多POST ajax请求,从来没有使用过stopPropagation。我不太理解你的情况,但也许这个链接会让你更好地理解我的意思是说我通过ajax的POST请求应该正常工作,但在我的情况下,它不工作,并试图找出原因。你使用的是什么版本的jQuery?也许只是试着让按钮保持单独,看看它是否发生了?评论不用于扩展讨论;这段对话已经结束。