You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

jQuery Ajax设置3秒Timeout无效,Deferred仍等待PHP300秒超时

问题原因

你设置的jQuery Ajax timeout没生效,是因为前端的超时是检测“服务器是否在指定时间内返回响应”,但你的PHP脚本一直在后台运行(直到触发自身300秒的max_execution_time错误),期间没有断开连接,所以客户端会一直等服务器输出,不会触发前端的超时。

PHP默认在脚本执行完之前不会向浏览器输出任何内容,连接处于“挂起”状态,jQuery没法判断服务器是不是在干活,只会傻等直到服务器返回结果(不管是成功还是致命错误)。

解决办法

1. 核心优化:后端分批处理(必须做)

批量地理编码本来就不该一次性处理大量地址,不仅容易超时,还会占用服务器资源。正确的做法是拆分任务:

  • 后端ajax.php接受page和limit参数,每次只处理N条地址(比如10条)
  • 前端循环发送请求,每次处理完一批再请求下一批,直到所有地址处理完成

前端修改代码

function initialize() {
    var map;
    var bounds = new google.maps.LatLngBounds();
    var mapOptions = {
        mapTypeId: 'roadmap'
    };

    map = new google.maps.Map(document.getElementById("mappa"), mapOptions);
    var infoWindow = new google.maps.InfoWindow(), marker, i;

    // 分批加载,初始页码1,每页10条
    loadLocationsByPage(1, 10, map, bounds);
}

function loadLocationsByPage(page, limit, map, bounds) {
    $.ajax({
        url: 'ajax.php',
        dataType: 'json',
        data: {page: page, limit: limit},
        timeout: 10000 // 单批处理耗时短,设置10秒足够
    }).done(function (result) {
        // 渲染当前批的标记
        result.data.forEach(item => {
            var position = new google.maps.LatLng(item.lat, item.lng);
            bounds.extend(position);
            new google.maps.Marker({
                position: position,
                map: map,
                title: item.nome
            });
        });

        // 如果还有下一页,继续请求
        if (result.hasMore) {
            loadLocationsByPage(page + 1, limit, map, bounds);
        } else {
            // 所有数据加载完成,调整地图视野
            map.fitBounds(bounds);
        }
    }).fail(function() {
        $.alert(`第${page}页加载超时,请重试`);
    });
}

google.maps.event.addDomListener(window, 'load', initialize);

后端ajax.php修改示例

<?php
// 单批处理不需要太长执行时间,设置为60秒足够
ini_set('max_execution_time', 60);

$page = $_GET['page'] ?? 1;
$limit = $_GET['limit'] ?? 10;
$offset = ($page - 1) * $limit;

// 替换成你的地址查询逻辑,比如从数据库取当前页的地址
$addresses = getAddressesFromDb($offset, $limit);
$latlngData = [];
foreach ($addresses as $addr) {
    // 调用地理编码API获取经纬度
    $latlng = geocodeAddress($addr['address']);
    if ($latlng) {
        $latlngData[] = [
            'lat' => $latlng['lat'],
            'lng' => $latlng['lng'],
            'nome' => $addr['nome']
        ];
    }
}

// 判断是否还有更多数据
$total = getTotalAddressesCount();
$hasMore = ($page * $limit) < $total;

echo json_encode([
    'data' => $latlngData,
    'hasMore' => $hasMore
]);
?>

2. 前端手动强制超时(应急用)

如果暂时没法改后端,要让前端在3秒后直接触发失败,可以自己封装Deferred,结合setTimeout手动中断请求:

function loadLocations() {
    var deferred = $.Deferred();
    var xhr = $.ajax({
        url: 'ajax.php',
        dataType: 'json'
    });

    // 手动设置3秒超时
    var timeoutId = setTimeout(function() {
        xhr.abort(); // 中断请求
        deferred.reject('timeout');
    }, 3000);

    xhr.done(function(data) {
        clearTimeout(timeoutId);
        deferred.resolve(data);
    }).fail(function() {
        clearTimeout(timeoutId);
        deferred.reject();
    });

    return deferred.promise();
}

这个方法会在3秒后主动中断请求,触发fail回调,但后端脚本还是会在服务器上继续跑直到超时,只是前端不等了。

3. 临时调整PHP超时(不推荐)

如果只是测试,可以在ajax.php开头临时延长执行时间,但这不是长久之计:

<?php
ini_set('max_execution_time', 600); // 设置为600秒(10分钟)
// 或者用set_time_limit(600);
?>

内容的提问来源于stack exchange,提问作者itajackass

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 11:10:55