对同一 URL 的第二次 AJAX 调用失败 - 但随机且很少工作

Posted

技术标签:

【中文标题】对同一 URL 的第二次 AJAX 调用失败 - 但随机且很少工作【英文标题】:2nd AJAX call to same URL fails - but works randomly and rarely 【发布时间】:2018-05-24 10:04:47 【问题描述】:

我正在尝试从 Web 服务获取响应,特别是将两个 WFS 图层从地理服务器添加到传单 Web 地图。每次加第一层都没问题,但大多数时候第二层失败,抱怨没有定义回调函数:

ReferenceError: getJson is not defined

但我很奇怪的是,第二层会被添加,只是有时。刷新页面并重试几乎总是会失败。

这是进行 ajax 调用的代码:

$(document).ready(function() 

...

    $("#add-network-button").on("click", function() setLocation("Moscow")) 

    function setLocation(locationName) 

        var networkParameters = 
            service: 'WFS',
            version: '1.0.0',
            request: 'GetFeature',
            typeName: 'netex:' + locationData[locationName].networkWFSName,
            maxFeatures: 99999,
            outputFormat: 'text/javascript',
            format_options: 'callback: getJson'
        ;

        addWebService(map, WFSURL, networkParameters)

        var buildingParameters = 
            service: 'WFS',
            version: '1.0.0',
            request: 'GetFeature',
            typeName: 'netex:' + locationData[locationName].buildingWFSName,
            maxFeatures: 99999,
            outputFormat: 'text/javascript',
            format_options: 'callback: getJson'
        ;

        addWebService(map, WFSURL, buildingParameters)

    

这里是addWebService 函数:

var addWebService = function(map, WFSURL, WFSParameters) 

    var leafletWFSParameters = L.Util.extend(WFSParameters);

    console.log(WFSURL + L.Util.getParamString(leafletWFSParameters));

    $.ajax(
        url: WFSURL + L.Util.getParamString(leafletWFSParameters),
        dataType: 'jsonp',
        jsonpCallback: 'getJson',
        success: handleJson,
        cache: false
    );

    // TODO: add style
    function handleJson(data) 
        L.geoJson(data, ).addTo(map);
    

【问题讨论】:

小更新:设置 ajax 调用参数async: false 似乎已经解决了这个问题,但我从那些比我更有经验的人那里听说这不是一个“正确”的解决方案,但我不是真的很清楚为什么。 【参考方案1】:

您正在使用jsonp,这意味着您返回的数据不是 JSON,而是调用全局定义函数(名称由 jsonpCallback 定义)的 javascript 代码。

jQuery 自动创建一个具有该名称的函数,执行网络请求,并且当该函数运行时,它会从全局范围内销毁它自己的引用。

您正在快速连续执行两次对addWebService() 的调用,这会触发两次jQuery $.ajax(jsonpCallback: 'getJson') 调用。第二个调用是覆盖全局定义的getJson 回调函数。当您的浏览器接收到第一个 jsonp 有效负载时,全局定义的 getJson 回调将被销毁。当接收到第二个 jsonp 有效负载时,它会尝试调用全局定义的 getJson 函数,但失败了。经典的比赛条件。

让我引用jQuery's documentation for the jsonpCallback parameter on $.ajax(),强调我的:

jsonp回调

类型:字符串或函数()

为 JSONP 请求指定回调函数名称。 将使用此值代替随机名称 由 jQuery 自动生成。 最好让 jQuery 生成一个唯一的名称,因为这样可以更轻松地管理 请求并提供回调和错误处理。你可能想要 当您想要启用更好的浏览器缓存时指定回调 GET 请求。

我建议您要么使用 JSONP 以外的其他传输格式,要么为每个请求使用不同的回调名称。

【讨论】:

如果我跳过参数(因此让它取一个随机名称),它会失败,因为它仍在寻找getJson。我在想这可能是geoserver本身的一个限制,它需要函数有这个名字。 是的,但那是因为您在代码的其他部分将 format_options: 'callback: getJson' 传递给 geoserver。

以上是关于对同一 URL 的第二次 AJAX 调用失败 - 但随机且很少工作的主要内容,如果未能解决你的问题,请参考以下文章

Asp .Net Core WebApi:异常的第二次http调用

Laravel csrf 令牌在 ajax 上第二次不匹配

KnockoutJS 绑定

我的 CustomDeserializer 类在同一类的第二个字段上第二次不起作用

用click事件调用ajax 第一次点击有用,第二次就失效了

从 jQuery 对 Mathjax 排版函数的第二次调用不起作用