多次切换点击调用相同 AJAX,不一致的数据库更新
Multiple toggle clicks calls same AJAX, inconsistent database updates
我的页面上有几个开关,全部使用 class psettings,它允许触发单个脚本执行 AJAX 调用以更新 MySQL 数据库中的标志 table。如果我慢慢点击,这很好用。我可以以正常速度单击所有按钮,并且数据库按预期更新但未选中,有时不会清除数据库中的标志。如果我走慢,在点击之间暂停,它工作正常。我无法阻止用户点击开关的速度有多快,但需要一种方法来确保更新一致,可能是延迟或刷新等。
<script type="text/javascript">
$('.psettings').change(function(){
//event.preventDefault();
var token = $("input[name=<?php echo csrf_token(); ?>").val();
var ename = this.name;
var evalue = ' ';
if($("input[type='checkbox']").is(":checked"))
{
var evalue = 'X';
}
$.ajax({
type: 'post',
headers: {'X-Requested-With': 'XMLHttpRequest'},
url: '<?php echo base_url('setprivacy');?>',
data: {'<?php echo csrf_token(); ?>' : token, 'element_name' : ename, 'checked' : evalue },
dataType: 'json',
success:function(data){
$('input[name="fmpfy_tk"]').val(data.csrf);
},
error:function(data)
{
$('input[name="fmpfy_tk"]').val(data.csrf);
alert('Error occurred ' + data.col_name);
}
});
});
</script>
<?php
echo form_open();
?>
<div class="row mt-3 pb-2">
<div class="col">
<h2 class="title-text grayer pb-1"><i class="fa-solid fa-eye-slash pe-2"></i>Privacy Settings</h2>
<div class="row mt-3 py-2 base-text">
<div class="col">
<div class="form-check form-switch">
<input class="form-check-input psettings" type="checkbox" role="switch" name="flag_display_fullname" value="">
<label class="form-check-label" for="flag_display_fullname">Display full name in profile and posts</label>
<i class="fa-solid fa-circle-info ps-3 off-black" rel="tooltip" title="<?php echo lang('Tooltips.display_fullname'); ?>"></i>
</div>
<div class="form-check form-switch">
<input class="form-check-input psettings" type="checkbox" role="switch" name="flag_display_smaccounts" value="">
<label class="form-check-label" for="flag_display_smaccounts">Display social media accounts on posts</label>
<i class="fa-solid fa-circle-info ps-3 off-black" rel="tooltip" title="<?php echo lang('Tooltips.display_sm_accounts'); ?>"></i>
</div>
<div class="form-check form-switch">
<input class="form-check-input psettings" type="checkbox" role="switch" name="flag_receive_fy_emails" value="">
<label class="form-check-label" for="flag_receive_fy_emails">Receive periodic emails from FY.</label>
<i class="fa-solid fa-circle-info ps-3 off-black" rel="tooltip" title="<?php echo lang('Tooltips.receive_fy_emails'); ?>"></i>
</div>
</div>
</div>
</div>
</div>
<?php
echo form_close();
?>
public function maintain_privacy_settings()
{
helper(['form','url']);
if ($this->request->isAJAX())
{
$UserModel = new \App\Models\User_model();
//Determine update column name
$element_name = $this->request->getPost('element_name');
$col_name;
switch ($element_name)
{
case 'flag_display_fullname':
$col_name = 'show_fullname';
break;
case 'flag_display_smaccounts':
$col_name = 'display_sm_accounts';
break;
case 'flag_receive_fy_emails':
$col_name = 'fy_notification_emails';
break;
}
if($UserModel->set_privacy_flag($this->data['userid'],$col_name,$this->request->getPost('checked')))
{
return json_encode(['success'=> 'success', 'csrf' => csrf_hash()]);
}
else
{
return json_encode(['error' => 'error', 'csrf' => csrf_hash(), 'col_name' => $this->request->getPost('element_name') ]);
}
}
}
当多个请求将被发送到服务器但它们的响应不会按顺序返回时,就会出现您的问题。所以服务器上存储的内容将与 UI.
上的存储内容不同
要解决此问题,您可以使用多种技术,但最简单的方法是阻止特定的 UI 元素,直到从服务器收到响应。为此,您可以在 ajax 调用之前禁用元素,然后在函数成功或失败时启用它。
您还可以为每个请求分配一个序列号,并应用最高的序列号并忽略其余的。
您还可以为您的请求实现一个队列并按顺序处理它们。
编辑:
您的 jquery 代码也有问题。您没有得到特定输入的检查状态。试试下面的方法:
if($(`input[name='${ename}']`).is(":checked"))
{
var evalue = 'X';
}
我的页面上有几个开关,全部使用 class psettings,它允许触发单个脚本执行 AJAX 调用以更新 MySQL 数据库中的标志 table。如果我慢慢点击,这很好用。我可以以正常速度单击所有按钮,并且数据库按预期更新但未选中,有时不会清除数据库中的标志。如果我走慢,在点击之间暂停,它工作正常。我无法阻止用户点击开关的速度有多快,但需要一种方法来确保更新一致,可能是延迟或刷新等。
<script type="text/javascript">
$('.psettings').change(function(){
//event.preventDefault();
var token = $("input[name=<?php echo csrf_token(); ?>").val();
var ename = this.name;
var evalue = ' ';
if($("input[type='checkbox']").is(":checked"))
{
var evalue = 'X';
}
$.ajax({
type: 'post',
headers: {'X-Requested-With': 'XMLHttpRequest'},
url: '<?php echo base_url('setprivacy');?>',
data: {'<?php echo csrf_token(); ?>' : token, 'element_name' : ename, 'checked' : evalue },
dataType: 'json',
success:function(data){
$('input[name="fmpfy_tk"]').val(data.csrf);
},
error:function(data)
{
$('input[name="fmpfy_tk"]').val(data.csrf);
alert('Error occurred ' + data.col_name);
}
});
});
</script>
<?php
echo form_open();
?>
<div class="row mt-3 pb-2">
<div class="col">
<h2 class="title-text grayer pb-1"><i class="fa-solid fa-eye-slash pe-2"></i>Privacy Settings</h2>
<div class="row mt-3 py-2 base-text">
<div class="col">
<div class="form-check form-switch">
<input class="form-check-input psettings" type="checkbox" role="switch" name="flag_display_fullname" value="">
<label class="form-check-label" for="flag_display_fullname">Display full name in profile and posts</label>
<i class="fa-solid fa-circle-info ps-3 off-black" rel="tooltip" title="<?php echo lang('Tooltips.display_fullname'); ?>"></i>
</div>
<div class="form-check form-switch">
<input class="form-check-input psettings" type="checkbox" role="switch" name="flag_display_smaccounts" value="">
<label class="form-check-label" for="flag_display_smaccounts">Display social media accounts on posts</label>
<i class="fa-solid fa-circle-info ps-3 off-black" rel="tooltip" title="<?php echo lang('Tooltips.display_sm_accounts'); ?>"></i>
</div>
<div class="form-check form-switch">
<input class="form-check-input psettings" type="checkbox" role="switch" name="flag_receive_fy_emails" value="">
<label class="form-check-label" for="flag_receive_fy_emails">Receive periodic emails from FY.</label>
<i class="fa-solid fa-circle-info ps-3 off-black" rel="tooltip" title="<?php echo lang('Tooltips.receive_fy_emails'); ?>"></i>
</div>
</div>
</div>
</div>
</div>
<?php
echo form_close();
?>
public function maintain_privacy_settings()
{
helper(['form','url']);
if ($this->request->isAJAX())
{
$UserModel = new \App\Models\User_model();
//Determine update column name
$element_name = $this->request->getPost('element_name');
$col_name;
switch ($element_name)
{
case 'flag_display_fullname':
$col_name = 'show_fullname';
break;
case 'flag_display_smaccounts':
$col_name = 'display_sm_accounts';
break;
case 'flag_receive_fy_emails':
$col_name = 'fy_notification_emails';
break;
}
if($UserModel->set_privacy_flag($this->data['userid'],$col_name,$this->request->getPost('checked')))
{
return json_encode(['success'=> 'success', 'csrf' => csrf_hash()]);
}
else
{
return json_encode(['error' => 'error', 'csrf' => csrf_hash(), 'col_name' => $this->request->getPost('element_name') ]);
}
}
}
当多个请求将被发送到服务器但它们的响应不会按顺序返回时,就会出现您的问题。所以服务器上存储的内容将与 UI.
上的存储内容不同要解决此问题,您可以使用多种技术,但最简单的方法是阻止特定的 UI 元素,直到从服务器收到响应。为此,您可以在 ajax 调用之前禁用元素,然后在函数成功或失败时启用它。
您还可以为每个请求分配一个序列号,并应用最高的序列号并忽略其余的。
您还可以为您的请求实现一个队列并按顺序处理它们。
编辑:
您的 jquery 代码也有问题。您没有得到特定输入的检查状态。试试下面的方法:
if($(`input[name='${ename}']`).is(":checked"))
{
var evalue = 'X';
}