Ajax调用写入数据库异常:仅成功写入前10条左右记录
问题排查与解决方案
首先,咱们来拆解下你遇到的问题:客户端能拿到完整的API返回,但批量写入数据库时只有前10条左右成功,后面的没动静。主要问题出在客户端无节制的并发请求和服务器端未正确响应请求这两个点上,咱们一步步来解决:
1. 服务器端的核心问题:未返回响应
你的服务器POST路由处理完数据库插入后,没有给客户端返回任何响应(res.send/res.end)。浏览器对同一个域名的并发HTTP请求数是有限制的(通常是6-8个),当这些请求一直处于pending状态时,浏览器会暂停发送后续请求——这就是为什么只有前几条能成功写入,后面的请求根本没发出去!
修改服务器端代码,确保每次处理完都返回响应:
app.post("/api/cryptodata", function(req, res){ connection.query('INSERT INTO pricings SET ?', req.body, function(error, result, fields){ if(error) { console.error("插入失败:", error); return res.status(500).json({ success: false, error: error.message }); } console.log("插入成功:", req.body.currency_id); res.json({ success: true, insertId: result.insertId }); }) })
2. 客户端的问题:无控制的并发请求
你在循环里直接发起大量$.ajax请求,这些请求会同时发送,不仅会触发浏览器的并发限制,还可能导致服务器压力过大,甚至被判定为恶意请求。咱们需要控制请求并发数,或者分批处理请求。
方案一:使用Promise分批处理(推荐)
把请求包装成Promise,然后分批执行,比如每次处理10个请求,等一批完成后再处理下一批:
function coinMarketCapAPICall(){ var queryUrl = "https://api.coinmarketcap.com/v1/ticker/?limit=0"; $.ajax({ url: queryUrl, method: "GET" }) .done(async function(response){ console.log("拿到的总数据条数:", response.length); // 定义每批处理的数量 const batchSize = 10; // 分批处理 for(let i=0; i<response.length; i+=batchSize){ const batch = response.slice(i, i+batchSize); // 把当前批次的请求转为Promise数组 const requests = batch.map(item => { const newCryptoRow = { currency_id: item.id, name: item.name, symbol: item.symbol, rank: item.rank, price_usd: item.price_usd, price_btc: item.price_btc, twentyfour_volume_usd: item['24h_volume_usd'], market_cap_usd: item.market_cap_usd, available_supply: item.available_supply, total_supply: item.total_supply, max_supply: item.max_supply, percent_change_1h: item.percent_change_1h, percent_change_24h: item.percent_change_24h, percent_change_7d: item.percent_change_7d, last_updated: item.last_updated }; // 把$.ajax转为Promise return new Promise((resolve, reject) => { $.ajax("/api/cryptodata",{ type: "POST", data: newCryptoRow }) .done(resolve) .fail(reject); }); }); // 等待当前批次所有请求完成 try { await Promise.all(requests); console.log(`批次 ${Math.floor(i/batchSize)+1} 处理完成`); } catch(err) { console.error(`批次 ${Math.floor(i/batchSize)+1} 中有请求失败:`, err); } } }) .fail(function(err){ console.error("获取CoinMarketCap数据失败:", err); }); }
方案二:串行处理(简单但速度慢)
如果不需要太高的效率,也可以一个接一个地发送请求,确保每个请求完成后再发下一个:
function coinMarketCapAPICall(){ var queryUrl = "https://api.coinmarketcap.com/v1/ticker/?limit=0"; $.ajax({ url: queryUrl, method: "GET" }) .done(function(response){ console.log("拿到的总数据条数:", response.length); // 定义递归处理函数 function processItem(index){ if(index >= response.length){ console.log("所有数据处理完成"); return; } const item = response[index]; const newCryptoRow = { currency_id: item.id, name: item.name, symbol: item.symbol, rank: item.rank, price_usd: item.price_usd, price_btc: item.price_btc, twentyfour_volume_usd: item['24h_volume_usd'], market_cap_usd: item.market_cap_usd, available_supply: item.available_supply, total_supply: item.total_supply, max_supply: item.max_supply, percent_change_1h: item.percent_change_1h, percent_change_24h: item.percent_change_24h, percent_change_7d: item.percent_change_7d, last_updated: item.last_updated }; $.ajax("/api/cryptodata",{ type: "POST", data: newCryptoRow }) .done(function(){ console.log(`第 ${index+1} 条数据写入成功`); // 处理下一条 processItem(index+1); }) .fail(function(err){ console.error(`第 ${index+1} 条数据写入失败:`, err); // 即使失败也继续处理下一条(或者根据需求调整) processItem(index+1); }); } // 从第一条开始处理 processItem(0); }) .fail(function(err){ console.error("获取CoinMarketCap数据失败:", err); }); }
3. 额外排查点
- 检查服务器端的数据库连接是否有连接数限制,如果插入请求太多,可能会耗尽数据库连接池,导致后续请求失败。
- 在客户端的
$.ajax的fail回调里打印错误,看看后面的请求是不是因为服务器错误、网络问题或者数据格式问题失败了。 - 查看服务器端的日志,确认是否有后续请求到达,以及数据库插入时是否有错误(比如字段类型不匹配、空值约束等)。
内容的提问来源于stack exchange,提问作者Pat Doyle
相关产品推荐
相关产品推荐

