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

u23*_*238 3 ajax jquery json jsonp

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

我想从 Web 服务器获取 JSON 文件。JSON 文件已由 JSONLint 检查,因此验证语法正确。JSON 数据是从类似于以下的 URL 检索的: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);
    }
});
Run Code Online (Sandbox Code Playgroud)

这是错误:

:parsererror 错误:未调用 jQuery222030055767520832166_1465026956736

到目前为止我所做的:

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

更新1

我的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"
}]
Run Code Online (Sandbox Code Playgroud)

UPDATE2 根据 @Michael 的解释,我更新了标头和 ajax 代码 dataType:"json" 但出现 Access-Control-Allow-Origin 错误。我的 json 文件的标头检查结果:

$.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);
    }
});
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?PS:另外,我尝试编写另一种方法(IfModule)仍然有问题。

Mic*_*ill 5

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

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

  • Access-Control-Allow-Origin:您的服务器
  • 访问控制允许方法:GET、PUT、POST、DELETE、OPTIONS
  • 访问控制最大年龄:3600
  • 访问控制允许标头

完成后,您可以简单地执行 JSON(而不是 JSONP)Ajax 调用,然后就可以了。

如果由于某种原因您不能依赖 CORS,并且您确实控制远程服务器,则只需将数据返回为 JSONP 而不是 JSON。

但是,如果您无法控制远程服务器或由于某种原因无法使用 CORS,事情很快就会变得奇怪。如何通过 JavaScript 发送跨域 POST 请求?很好地解释了如何使用 iframe 和window.postMessage. 当然,该示例适用于 POST,但如果您只是尝试从远程服务器获取数据,则所有信息都有效。

在这种情况下很难给出准确的答案,因为根本没有关于您是否控制远程服务器的信息,也没有关于您自己的服务器正在使用什么语言/技术堆栈的信息文章4 jQuery 跨域 AJAX 请求方法很好地介绍了各种解决方案,其中之一可能会解决您的问题(在决定使用一种方法之前,请务必注意每种解决方案的缺点)。

如果此时你还陷入僵局,你应该考虑使用你自己的服务器作为代理,这样Ajax调用可以到你的服务器,然后你的服务器可以跨域调用远程服务器检索数据。这将导致响应时间更长,但会为您提供所需的信息,并完全控制流程的各个方面。通常只需几行代码即可完成此操作,但确实需要在服务器上完成。

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

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

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

有关 CORS 的更多信息,请参阅W3C 跨源资源共享规范,了解 CORS 工作原理的详细信息。您还应该查看html5rocks.com 使用 CORS中的详细报道,因为这涵盖了 CORS 如何工作以及在 CORS 环境中可以执行的操作的大量基础知识。