如何在PHP中循环调用file_get_contents直至获取非空JSON?
解决Nanopool API不稳定的循环重试方案
我明白你被这个不稳定的API折腾得够呛——每几次调用才成功一次确实闹心。你之前尝试do...while没起效,大概率是没正确判断“有效响应”的标准,或者没处理请求失败、JSON解析错误的情况。下面给你一套可靠的实现方案:
核心思路
我们需要循环调用API,直到获取到非空、能正确解析为JSON、且包含有效data字段的响应,同时加上重试次数限制和间隔等待,避免无限循环或者频繁请求被限流。
改进后的代码
<?php $apiUrl = "https://api.nanopool.org/v1/eth/payments/0x218494b2284a5f165ff30d097d3d7a542ff0023B"; $maxRetries = 10; // 最大重试次数,避免无限循环 $retryDelay = 2; // 每次重试间隔秒数 $success = false; $decode = null; // 设置file_get_contents的上下文,添加超时时间 $context = stream_context_create([ 'http' => [ 'timeout' => 5 // 5秒超时,防止请求卡死 ] ]); do { $json = file_get_contents($apiUrl, false, $context); $maxRetries--; // 检查响应是否非空,且JSON解析成功 if (!empty($json) && ($decode = json_decode($json, true)) !== false) { // 检查data字段是否存在且非空 if (isset($decode['data']) && !empty($decode['data'])) { $success = true; break; } } // 未成功则等待后重试 if ($maxRetries > 0) { sleep($retryDelay); } } while ($maxRetries > 0 && !$success); // 处理最终结果 if ($success) { foreach($decode['data'] as $val){ echo date('Y-m-d',$val['date']).' -- '.$val['amount'].' -- '.$val['txHash'].' -- '.$val['confirmed']; echo "<br/>"; } } else { echo "多次尝试后仍无法获取有效数据,请稍后再试"; } ?>
关键细节说明
- 重试次数限制:设置
$maxRetries避免无限循环,哪怕API一直挂了也能终止程序 - 请求超时:通过
stream_context_create设置HTTP超时,防止请求长时间卡死 - 多层有效性判断:
- 先判断
$json非空(避免请求失败返回空字符串) - 判断
json_decode成功(避免返回无效JSON格式) - 检查
data字段存在且非空(确保返回的是有意义的支付数据)
- 先判断
- 间隔等待:每次重试前
sleep几秒,减少对API的压力,也避免触发限流
进阶优化:用cURL替代file_get_contents
如果file_get_contents还是不够稳定,推荐用cURL,它能更灵活地处理HTTP错误(比如4xx/5xx状态码):
<?php $apiUrl = "https://api.nanopool.org/v1/eth/payments/0x218494b2284a5f165ff30d097d3d7a542ff0023B"; $maxRetries = 10; $retryDelay = 2; $success = false; $decode = null; do { $ch = curl_init($apiUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 5); $json = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $maxRetries--; // 检查HTTP状态码为200,且JSON解析成功,data有效 if ($httpCode === 200 && !empty($json) && ($decode = json_decode($json, true)) !== false) { if (isset($decode['data']) && !empty($decode['data'])) { $success = true; break; } } if ($maxRetries > 0) { sleep($retryDelay); } } while ($maxRetries > 0 && !$success); // 后续处理和上面一致... ?>
cURL能直接获取HTTP状态码,更容易判断API是否真的返回了成功响应,比file_get_contents容错性更强。
内容的提问来源于stack exchange,提问作者R_life_R
相关产品推荐
相关产品推荐

