DataTables重复初始化报错:无刷新定时刷新数据问题求助
Hey there, let’s break down why you’re hitting that error and how to fix it. The core issue is you’re trying to re-initialize the DataTable every time your executeQuery function runs (inside the complete callback). Once DataTables is set up on a table, you can’t run $('#dataTable').DataTable() again without destroying the existing instance first—hence the "cannot reinitialise" warning.
Here’s the step-by-step solution:
1. Initialize DataTable Only Once
Move the DataTable initialization to your $(document).ready() function so it runs just once when the page loads. We’ll set it up with empty initial state since we’ll populate data dynamically later.
2. Update Data Using DataTables API
Instead of inserting a new <tbody> every time you fetch data, use DataTables’ built-in methods to clear existing rows, add new data, and refresh the table. This is the proper, supported way to update data without reinitializing.
3. Clean Up Timer Logic
Your current timer setup works, but we’ll tweak it to avoid any accidental duplicate timers and make the flow more intuitive.
Modified Full Code
Here’s your updated code with all fixes applied:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Crypto Market Cap</title> <link rel="icon" type="image/png" href="imgs/favicon.ico" /> <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css"> <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css"> <link rel="stylesheet" type="text/css" href="css/spritesheet.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <script type="text/javascript" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-112760236-1"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-112760236-1'); </script> <style> #tableHeader tr td { font-weight:bold } </style> </head> <body> <img src="imgs/spritesheet.png" width="0" height="0" style="display: none"> <div class="container"> <div class="row" style="text-align:center;margin-bottom:30px"> <h2 class="col-xs-12"> Cryptocurrency Market Capitalizations </h2> <h5>$USD</h5> </div> <div class="row"> <div class="col-xs-12" style="padding:0"> <table id="dataTable" class="table table-bordered hover" style="margin:0 auto"> <thead id="tableHeader"> <tr> <td>#</td> <td>Name</td> <td>Price</td> <td>Market Cap</td> <td>Available Supply</td> <td>24 HR % Change</td> </tr> </thead> <tbody class="mainTable"></tbody> <!-- Add empty tbody to markup --> </table> </div> </div> <div class="row"> <div class="col-xs-12" style="text-align:center;margin-top:50px"> <img src="imgs/loading.gif" style="height:120px" id="loading"> </div> </div> </div> <script> // Store DataTable instance for easy API access let cryptoTable; function executeQuery() { $.ajax({ url: "http://coincap.io/front", type: "GET", dataType: "json", success: function (data) { // Clear existing rows from the table cryptoTable.clear(); var len = data.length; for (var i = 0; i < len; i++) { var numFormat = data[i].price.toLocaleString("en"); var numFormat1 = data[i].mktcap.toLocaleString("en"); var numFormat2 = data[i].supply.toLocaleString("en"); var lowerCaseName = data[i].long.toLowerCase(); // Add each row using DataTables' row.add() method cryptoTable.row.add([ i+1, `<span class='sprite sprite-${lowerCaseName} small_coin_logo'></span>${data[i].long} - ${data[i].short}`, `$${numFormat}`, `$${numFormat1}`, numFormat2, `<td class='marketChange'>${data[i].cap24hrChange}% </td>` ]); } // Refresh the table to show new data cryptoTable.draw(); }, complete: function() { $("#loading").addClass("hide"); } }); // Schedule the next update setTimeout(executeQuery, 5000); } $(document).ready(function() { // Initialize DataTable once on page load cryptoTable = $('#dataTable').DataTable({ "lengthMenu": [ 20, 50, 75, 100 ], "order": [[ 3, "desc" ]], language: { search: "" }, // Hide loading state once table is ready initComplete: function() { $("#loading").addClass("hide"); } }); // Set up search input styling and placeholder $('#dataTable_filter input[type="search"]').attr('placeholder', 'Search for coins'); $('#dataTable_filter input[type="search"]').css("padding-left","9px"); // Run first data fetch immediately (remove setTimeout if you want initial delay) executeQuery(); }); </script> </body> </html>
Key Changes Explained:
- Stored DataTable Instance: We created a
cryptoTablevariable to hold the DataTable instance, so we can easily use its API methods for updates. - Single Initialization: DataTable is set up once in
$(document).ready()instead of every time we fetch data. - API-Driven Updates: Used
clear()to remove old rows,row.add()to insert new data, anddraw()to refresh the table—no more reinitialization attempts. - Fixed tbody: Added an empty
<tbody>directly to the table markup instead of inserting it dynamically each time.
This should eliminate the "cannot reinitialise data table" error while keeping your auto-update functionality working smoothly.
内容的提问来源于stack exchange,提问作者Dan B

