【问题标题】:Jquery success function not firing using JSONPJquery成功函数未使用JSONP触发
【发布时间】:2011-01-23 17:53:38
【问题描述】:

一直在使用 jQuery 调用我在不同域中的服务。成功调用服务(我的调试点被触发),并返回正确的响应(我嗅探流量)。

我的问题主要是成功和失败回调没有被触发。我在 SO 上阅读了一些other posts,表明使用 JSONP 时不会触发错误事件。是成功事件的情况(可能是因为假设我提供了自己的回调函数),还是有办法触发我的成功回调。提前致谢。

$.ajax({
  type: "GET",
  url: urlOnDiffDomain,
  async: false,
  cache: false,
  dataType: 'jsonp',
  data: {},
  success: function(data, textStatus) {
    alert('success...');
  },
  error: function(xhr, ajaxOptions, thrownError) {
   alert('failed....');
  }
}); 

【问题讨论】:

  • 你在调试器中使用过这个吗?调用后,能否判断 jQuery 是否添加了一个名为“jsonpNNN”(其中 NNN 是数字)的全局函数?
  • 是的,jquery添加了全局函数jsonPXXXX

标签: javascript jquery jsonp


【解决方案1】:

好的。万一将来有人需要知道...事后看来,解决方案可能应该比以前更明显,但是您需要让网络响应直接写入响应。简单地返回一串 JSON 是行不通的,您需要有人构造它并将其流回。如果您确实这样做,我原始帖子中的代码将可以正常工作。

服务代码示例:

public void DoWork()
{
  //it will work without this, but just to be safe
  HttpContext.Current.Response.ContentType = "application/json"; 
  string qs = HttpContext.Current.Request.QueryString["callback"];
  HttpContext.Current.Response.Write(qs + "( [{ \"x\": 10, \"y\": 15}] )");
}

为了明确起见,这是客户端代码。

function localDemo(){
  $.getJSON("http://someOtherDomain.com/Service1.svc/DoWork?callback=?",
    function(data){
      $.each(data, function(i,item){            
        alert(item.x);
      });
  });
}

如果有更好的方法可以做到这一点,我会全力以赴。对于其他所有人,我知道 WCF 4.0 中有一些原生支持 JSONP 的概念。此外,出于安全目的,您可能想要做一点checking - 尽管我没有进行太多调查。

【讨论】:

  • 在 .NET 中创建 JSONP 服务的最简单方法是使用 HTTP 处理程序,然后没有要抑制的页面标记,您只需写入响应流。
  • 出于好奇:当您没有将字符串写入响应流时,您是如何“返回”字符串的?
  • 同意古法。删除 WCF 为您提供的默认 JSON 包装器也无济于事。您可以解决它,但这只是要记住的另一件事。 A:天真地做一个返回“东西”;
  • 如果您使用回调包装 JSON 数据,我认为内容类型不是 application/json。我使用文本/javascript。
  • 感谢帮助我的兄弟。
【解决方案2】:

服务器响应时调用success 回调方法。 $.ajax 方法设置一个函数,通过调用success 回调方法来处理响应。

success 方法未被调用的最可能原因是服务器的响应不正确。 $.ajax 方法在callback 查询字符串中发送一个值,服务器应将其用作 JSONP 响应中的函数名。如果服务器使用不同的名称,则永远不会调用 $.ajax 方法设置的函数。

如果服务器不能使用callback 查询字符串中的值来设置响应中的函数名称,您可以指定$.ajax 方法应该从服务器获得的函数名称。将属性jsonpCallback添加到选项对象中,并将值设置为服务器在响应中使用的函数的名称。

例如,如果 $.ajax 方法使用 URL http://service.mydomain.com/getdata?callback=jsonp12345 向服务器发送请求,则服务器应以如下所示的内容进行响应:

jsonp12345({...});

如果服务器忽略了callback 查询字符串,而是以如下方式响应:

mycallback({...});

然后您必须通过向选项对象添加属性来覆盖函数名称:

$.ajax({
  url: urlOnDiffDomain,
  dataType: 'jsonp',
  data: {},
  success: function(data, textStatus) {
    alert('success...');
  },
  jsonpCallback: 'mycallback'
});

【讨论】:

  • 我已经更改了从我的服务返回的值。现在看起来像这样: string qs = HttpContext.Current.Request.QueryString["callback"];返回 qs + "({'d':'s'})";给定以下客户端代码: var url = 'some.other.domain/service/serviceName.svc/param1/1/param2/2'; $.ajax({ url: url, dataType: 'jsonp', data: {}, jsonpCallback: 'mycallback', success: function(data, textStatus) { alert(data); } }) 响应的内容看起来像: "jsonp1267721964115({'d':'s'})" 尽管有属性,似乎它附加了一个回调函数?
  • @rhythmaddict:你使用的是什么版本的 jQuery?您需要 1.4 或更高版本才能使用 jsonpCallback 属性。但是,当您更改服务器代码以正确使用回调查询字符串时,您不需要使用 jsonpCallback 属性。
【解决方案3】:

试试

$.getJSON(urlOnDiffDomain, function(data, textStatus){
    alert('success...');
});

通常对我有用。您需要添加 &callback=?到 urlOnDiffDomain,其中 jQuery 会自动替换 JSONP 中使用的回调。

不触发错误回调,但可以使用全局$.ajaxError,像这样

$('.somenode').ajaxError(function(e, xhr, settings, exception) {
    alert('failed');
});

【讨论】:

  • 服务返回字符串的方式与我在上面的第一条评论中指出的方式相同。如果我以 &callback=? 结束我的 URL,我会得到一个 http 403。如果我以 ?callback= 结束?,我得到了服务,但是我的成功事件仍然没有被触发:-? (Jquery 确实创建了 JSONPXXXX 函数)
【解决方案4】:

这不是您问题的完整答案,但我认为路过的人想知道这一点:

当你处理JSONP from WCF REST时尝试使用:

[JavascriptCallbackBehavior(UrlParameterName = "$callback")]

为您的服务实施;这应该为您提供开箱即用的 JSONP。

【讨论】:

    【解决方案5】:
        $.ajax({
                    url:' <?php echo URL::site('ajax/editing?action=artistSeracher') ?>',
                    dataType: "json",
                    data: {
                        featureClass: "P",
                        style: "full",
                        maxRows: 12,
                        artist: request.term
                    },
                    success: function( data ) {
                        response( $.map( data, function( item ) {
                            return {
                                label: item.artist,
                                value: item.artist,
                                id: item.id
                            }
                        }));
                    },
                    error: function (xhr, ajaxOptions, thrownError) {
                        alert(xhr.status);
                        alert(thrownError);
                      }
                });
    

    【讨论】:

    • 发布答案时不要只提供代码。请解释您的代码将做什么或它与原始海报示例有何不同。如果您可以向原始发帖者解释,那么答案将最有效,以便他们了解它在做什么。
    猜你喜欢
    • 2013-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 2012-05-04
    相关资源
    最近更新 更多