Javascript与JSON缓存异常:Import后Refresh数据未正确提交
功能说明
- PHP模块读取CSV文件并将其数据转换为数组
- 通过HTML与PHP循环构建表格,展示CSV数据
- 表格的每一行均包含「Import Risk」按钮和「Refresh」按钮
- 点击「Import Risk」按钮会触发AJAX请求至
ajax-import.php,发送该行关联的JSON数据 - 解析
ajax-import.php的响应,若成功则更新表格行的风险信息或错误提示 - 每行的JSON数据存储在「Import Risk」按钮的
data-json属性中 - 点击「Refresh」按钮会触发AJAX请求至
refresh.php,获取该行的最新数据并更新表格行
问题描述
点击「Import Risk」按钮后,再点击「Refresh」按钮时,data-json属性已被刷新,但再次点击「Import Risk」按钮时,发送至ajax-import.php的JSON仍是首次点击Import时的初始版本。
诉求
实现点击「Refresh」按钮时可随时刷新data-json,且更新后的JSON能被正确发送至ajax-import.php进行处理。
代码实现
<!-- Start Table Content --> <div class="row"> <div class="col-12"> <div class="card"> <div class="card-body"> <h2>CSV File Contents</h2> <?php $csvtoarray_clean = sanitize_csv_file($file_path); ?> <?php // Convert the CSV data to an array $csvtoarray = array_map('str_getcsv', explode("\n", $csvtoarray_clean)); ?> <div class="table-responsive"> <table class="table table-bordered"> <thead> <tr> <th>#</th> <?php foreach($csvtoarray[0] as $col): ?> <th><?= htmlspecialchars($col) ?></th> <?php endforeach; ?> <th>JSON Output</th> <th>Actions</th> </tr> </thead> <tbody> <?php for($i=1; $i<count($csvtoarray); $i++): ?> <tr> <td><?= $i; ?></td> <?php foreach($csvtoarray[$i] as $cell): ?> <td><?= htmlspecialchars($cell) ?></td> <?php endforeach; ?> <?php $json_data = processJson(json_encode(array_combine($csvtoarray[0], $csvtoarray[$i])),$file_ref); ?> <td style="min-width: 550px;"> <code> <?php echo removeEmptyValues($json_data);?> <?php $validation_response = json_decode($json_data, true); ?> </code> </td> <td class="response-col"> <?php if ($validation_response['status'] == 'error'): ?> <strong>There are errors on this row of data:</strong> <?php foreach ($validation_response['errors'] as $error): ?> <li><?= htmlspecialchars($error) ?></li> <button class="refresh-btn btn btn-secondary" data-row="<?= $i ?>" data-hash="<?= md5(serialize($csvtoarray[$i])) ?>">Refresh</button> <?php endforeach; ?> <?php else: ?> <div class="alert alert-danger" role="alert" style="display: none;"></div> <div class="btn-group" role="group" aria-label="Actions"> <button class="import-button btn btn-primary" data-row="<?= $i ?>" data-json="<?php echo htmlspecialchars(removeEmptyValues($json_data)) ?>">Import Risk</button> <button class="refresh-btn btn btn-secondary" data-row="<?= $i ?>" data-hash="<?= md5(serialize($csvtoarray[$i])) ?>">Refresh</button> </div> <?php endif; ?> </td> </tr> <?php endfor; ?> </tbody> </table> </div> </div> </div> </div> </div> <!-- End Table Contents --> <script> $(document).ready(function() { // Handle import button click $(document).on('click', '.import-button', function() { var json_data = $(this).data('json'); var button = $(this); var alert = button.closest('tr').find('.alert'); alert.hide(); $.ajax({ type: 'POST', url: 'ajax-import.php?cache=' + new Date().getTime(), // Add cache-busting parameter to the URL data: { json_data: button.data('json'), // Fetch the latest data-json value from the button cacheBuster: new Date().getTime() // Cache-busting parameter }, beforeSend: function(xhr) { xhr.setRequestHeader('Cache-Control', 'no-cache'); }, success: function(response) { try { var data = JSON.parse(response); var risk_number = data.result.riskNumber; var risk_url = data.result.riskURL; var status = data.result.status; var responseText = data.result.responseText; var errorText = data.result.errorText; if (risk_url !== undefined) { button.closest('tr').find('.response-col').html('<a href="' + risk_url + '" class="btn btn-primary" target="_blank">' + risk_number + '</a>'); } else { var alertContent = '<h4 class="alert-heading">' + responseText + '</h4>' + errorText; alert.html(alertContent); alert.show(); } // Log the data being sent to the import script console.log('Import Data:', button.data('json')); // Log the latest data-json value // Refresh the data in the table row updateDataAndDOM(button, response); } catch (error) { console.error('Error parsing JSON:', error); } }, error: function(xhr, status, error) { var errorMessage = 'Error: ' + error; alert.html(errorMessage); alert.show(); button.text('Failed'); button.addClass('btn-danger'); } }); }); // Function to update JSON data and DOM elements function updateDataAndDOM(refreshButton, refreshedData) { var row = refreshButton.data('row'); var refreshedRowData = JSON.parse(refreshedData); var rowDataElements = refreshButton.closest('tr').find('td:not(.response-col)'); rowDataElements.each(function(index) { var header = $(this).closest('table').find('th').eq(index).text(); var newData = refreshedRowData[header]; if (newData !== undefined) { $(this).text(newData); } }); importButton = refreshButton.closest('tr').find('.import-button[data-row="' + row + '"]'); importButton.attr('data-json', refreshedData); // Update the data-json attribute } // Handle refresh button click $(document).on('click', '.refresh-btn', function() { var refreshButton = $(this); var row = refreshButton.data('row'); var hash = refreshButton.data('hash'); $.ajax({ url: 'refresh.php', data: { row: row, hash: hash, csvFilePath: '<?php echo $file_path; ?>', timestamp: new Date().getTime() // Append timestamp as a parameter }, type: 'GET', dataType: 'json', success: function(response) { if (response.status === 'refreshed') { var refreshedData_raw = response.refreshed_data; var refreshedData = JSON.stringify(refreshedData_raw); console.log('Refreshed Data:', refreshedData_raw); updateDataAndDOM(refreshButton, refreshedData); } else { console.log(response.message); var emptyData = '{}'; updateDataAndDOM(refreshButton, emptyData); } }, error: function(xhr, status, error) { console.log('Error: ' + error); var emptyData = '{}'; updateDataAndDOM(refreshButton, emptyData); } }); }); }); </script>
问题原因与修复方案
核心原因
jQuery的data()方法会将DOM元素的data-*属性值缓存到内存中,后续调用data('json')时优先读取缓存值,而非最新的DOM属性值。你的代码中updateDataAndDOM函数仅用attr('data-json', refreshedData)更新了DOM属性,但未同步更新jQuery的缓存,导致「Import Risk」点击时仍读取旧的缓存值。
修复步骤
方案1:同步DOM属性与jQuery缓存
修改updateDataAndDOM函数,在更新DOM属性后,同步更新jQuery的data缓存:
function updateDataAndDOM(refreshButton, refreshedData) { var row = refreshButton.data('row'); var refreshedRowData = JSON.parse(refreshedData); var rowDataElements = refreshButton.closest('tr').find('td:not(.response-col)'); rowDataElements.each(function(index) { var header = $(this).closest('table').find('th').eq(index).text(); var newData = refreshedRowData[header]; if (newData !== undefined) { $(this).text(newData); } }); // 修正:添加var声明避免全局变量污染,同时同步缓存 var importButton = refreshButton.closest('tr').find('.import-button[data-row="' + row + '"]'); importButton.attr('data-json', refreshedData); // 更新DOM属性 importButton.data('json', refreshedData); // 同步jQuery缓存 }
方案2:直接读取DOM属性(跳过缓存)
如果不想维护缓存,可在「Import Risk」的点击事件中直接读取DOM的data-json属性值,而非依赖jQuery的data()缓存:
$(document).on('click', '.import-button', function() { var button = $(this); // 修正:直接读取DOM属性,跳过jQuery缓存 var json_data = button.attr('data-json'); var alert = button.closest('tr').find('.alert'); alert.hide(); $.ajax({ type: 'POST', url: 'ajax-import.php?cache=' + new Date().getTime(), data: { json_data: json_data, // 使用直接读取的最新值 cacheBuster: new Date().getTime() }, // 后续代码保持不变 }); });
额外优化提示
- 原代码中
importButton变量未用var/let/const声明,会造成全局变量污染,建议添加var或const约束作用域。 - 成功导入后替换
response-col内容时,会移除「Import Risk」和「Refresh」按钮,若后续仍需对该行进行操作,需保留按钮或重新渲染操作区域。
内容的提问来源于stack exchange,提问作者Claud
相关产品推荐
相关产品推荐

