JSONP的jQuery.ajax()返回200,但解析错误运行错误回调而不是成功回调

时间:2016-06-04 08:17:43

标签: jquery json ajax jsonp

首先,我知道网站上有类似的帖子,但没有一个能解决我的问题。

我想从Web服务器获取JSON文件。 JSONLint检查了JSON文件,因此验证语法是否正常。从类似于以下URL的URL检索JSON数据:www.examplewebsite.com/data.json

我的jQuery Ajax代码:

$.ajax({

    url:url",
    dataType:"jsonp",
    contentType: "application/json",
    type:"get",
    success:function(){
        console.log("OK");
    },
    error:function(data,status,error){
        console.log(data " "status+" "+error);
    }
});

这是错误:

  

:parsererror错误:未调用jQuery222030055767520832166_1465026956736

到目前为止我做了什么:

  • 添加了回调函数(jsonpCallback:fname)(我真的想知道如果我们必须为服务器端JSON添加回调函数吗?)函数fname有效(alert("OK");),但我仍然会收到错误。其中一条错误消息是“未定义未定义”
  • 添加了jsonp:false选项
  • 将dataType:jsonp更改为json,但出现Access-Control-Allow-Origin错误
  • 仔细检查生成的JSON是否有效

UPDATE1

我的json内容(用于测试):

[{
  "id": 1,
  "first_name": "Sara"
}, {
  "id": 2,
  "first_name": "Lois"
}, {
  "id": 3,
  "first_name": "Annie"
}, {
  "id": 4,
  "first_name": "Gregory"
}, {
  "id": 5,
  "first_name": "Fred"
}, {
  "id": 6,
  "first_name": "Antonio"
}, {
  "id": 7,
  "first_name": "Denise"
}, {
  "id": 8,
  "first_name": "Susan"
}, {
  "id": 9,
  "first_name": "Jeffrey"
}, {
  "id": 10,
  "first_name": "Jean"
}]

UPDATE2 根据@Michael的解释,我更新了header和ajax代码,dataType:“json”但是我得到了Access-Control-Allow-Origin错误。我的标题检查结果为json文件:

HTTP/1.1 200 OK => 
Date => Sun, 05 Jun 2016 00:21:59 GMT
Server => Apache
Last-Modified => Sat, 04 Jun 2016 22:27:58 GMT
Accept-Ranges => bytes
Content-Length => 440
Access-Control-Allow-Origin => *
Access-Control-Allow-Headers => origin, x-requested-with, content-type
Access-Control-Allow-Methods => PUT, GET, POST, DELETE, OPTIONS
Keep-Alive => timeout=10, max=200
Content-Type => application/json
Connection => close

有什么想法吗? PS:另外,我试着写另一个方法(IfModule)仍然有问题。

1 个答案:

答案 0 :(得分:3)

您尝试检索的数据是JSON,而不是JSONP。如您所见,通过Ajax从另一个域请求JSON将导致Access Control Allow Origin错误。 Ajax将允许从不同的域检索JSONP,但内容必须实际上是JSONP,或者您收到解析错误,如您所见。

那么,你能做什么?如果您控制服务器请求JSON数据,您可以通过响应标头处理来自您的域的请求。您只需要设置这些标题:

  • Access-Control-Allow-Origin:您的服务器
  • 访问控制允许方法:GET,PUT,POST,DELETE,OPTIONS
  • Access-Control-Max-Age:3600
  • 接入控制允许接头

有了这个,你可以简单地做一个JSON(而不是JSONP)Ajax调用,然后你就可以了。

如果您出于某种原因无法依赖CORS,并且执行控制远程服务器,只需将数据作为JSONP而不是JSON返回。

但是,如果您不控制远程服务器或因某些原因无法使用CORS,那么事情很快就会变得怪异。 How do I send a cross-domain POST request via JavaScript?的答案很好地解释了如何使用iframe和window.postMessage。当然,该示例适用于POST,但如果您只是尝试从远程服务器进行GET,则所有信息都会保留。

在这种情况下,非常很难给出准确的答案,因为根本没有关于您是否控制远程服务器的信息,也没有关于您自己的服务器使用的语言/技术堆栈的信息。文章4 jQuery Cross-Domain AJAX Request methods中有各种解决方案的优秀报道,其中一个可能会解决您的问题(请务必在决定之前注意每个解决方案的缺点)。

如果此时仍处于僵局,您应该考虑使用自己的服务器作为代理,以便可以对您的服务器进行Ajax调用,然后您的服务器可以进行跨域调用远程服务器检索数据。这将导致更长的响应时间,但是可以完全 您所需要的,并完全控制流程的每个方面。这通常只需几行代码,但确实需要在服务器上完成。

考虑这个Ruby on Rails代理示例:

def json_proxy
  Net::HTTP.start("www.examplewebsite.com") do |http|
    render json: http.get("/data.json")
  end
end

您的服务器语言和/或技术堆栈可能不同,但这是它的要点。您可以根据需要修改和添加新功能,包括能够通过将请求详细信息传递给代理,为所有请求使用单个代理。您可以使用像这样的代理执行验证,替换甚至合并多个响应。它可以是您工具带中的强大工具。

有关CORS的更多信息,请参阅W3C Cross-Origin Resource Sharing规范以获取有关CORS如何工作的详细信息。您还应该查看html5rocks.com Using CORS中的精细覆盖,因为这涵盖了CORS如何工作以及您在CORS环境中可以执行的操作的基础知识。