JSONP请求返回错误:“未捕获的SyntaxError:意外的标记:”

25

我正在尝试使用以下jQuery代码向Stack Exchange API 发送请求:

$.ajax({                                                                                                                                                                                                        
    type: 'POST',                                                                                                                                                                                                 
    url: 'http://api.stackoverflow.com/1.1/stats',                                                                                                                                              
    dataType: 'jsonp',                                                                                                                                                                                                
    success: function() { console.log('Success!'); },                                                                                                                                                                                       
    error: function() { console.log('Uh Oh!'); }                                                                                                                                                              
});   

但是当我在我的机器上用FireFox或Chrome打开文件并发出请求时,我会收到这个错误:

Resource interpreted as Script but transferred with MIME type application/json.
Uncaught SyntaxError: Unexpected token :
Uh Oh!

我不知道发生了什么事。我知道Stack Exchange API会对其响应进行Gzip压缩,这会导致任何问题吗?


你从服务器得到了什么?我得到了JSON - 而JSON不是JSON-P,它将数据封装在回调函数中,该函数必须在全局命名空间中,并且您在请求中告诉服务器(这是您的代码中没有看到的另一件事)。关键是,如果实际上是JSON,请不要告诉你的jQuery结果是JSONP。 - Mörre
3
因为在 StackOverflow 的其他地方建议使用 JSONP,所以我使用了它。当我使用 JSON 时,会出现这个错误:XMLHttpRequest cannot load http://api.stackoverflow.com/1.1/stats. Origin null is not allowed by Access-Control-Allow-Origin. - theabraham
不知道他们的API,但是从那个URL返回的内容显然是JSON,就像我说的一样。使用"dataType"只是告诉你的jQuery如何解释结果,而不是告诉服务器你想要JSONP。 - Mörre
2个回答

21

要使SO API工作,您必须设置一个非传统的参数。而不是传统的callback,您需要传递一个jsonp参数。

此外,您不能使用JSONP进行POST操作。

$.ajax({                                                                                                                                                                                                        
    type: 'GET',                                                                                                                                                                                                 
    url: 'http://api.stackoverflow.com/1.1/stats',                                                                                                                                              
    dataType: 'jsonp',                                                                                                                                                                                                
    success: function() { console.log('Success!'); },                                                                                                                                                                                       
    error: function() { console.log('Uh Oh!'); },
    jsonp: 'jsonp'                                                                                                                                                
});

使用传统的XMLHTTPRequest不可能进行跨域AJAX,这是出于安全原因(被称为同源策略)。

有一个解决方法。 script标签不受此限制。这意味着您可以在文档中插入调用URL的script标签。如果您在脚本中定义了一个全局可访问的函数,并告诉远程服务器该函数的名称,服务器可以通过调用该函数来传递包装数据的代码。

您在此遇到的困难是与StackOverflow API相关的。通常,您将在请求中使用callback参数,以告诉服务器您的函数的名称。但是,StackOverflow的API要求您改用jsonp参数。


1
"jsonp"是一个参数 - 但它的值是全局命名空间中一个函数的名称,一旦结果出来就会被调用。 - Mörre
1
这对于jQuery来说很好 - 我告诉(并展示)他服务器想要什么。了解背景而不是一个特定库的实现方式难道不是更好吗?“我只学会按红色按钮,但这个是绿色的,所以我无法打开灯,非常抱歉”。只是开个玩笑 :) (嗯,不完全是) - Mörre
1
是的,我们都知道这一点,你的观点是什么?请参考上文,我想我已经说得很清楚了。你更倾向于只告诉他关于jQuery(没错,那是他的问题)- 而我更倾向于扩大范围,告诉他它实际上是如何工作的,独立于所使用的库。 - Mörre
1
哇,哇!非常感谢你们两位的帮助。我认为这次提出一个关于库/API的问题是合适的。我以前从未听说过JSONP,在我的JSON请求无法正常工作时感到很烦恼(而其他API则毫不费力地工作)。我已经到了一种只能靠试错来解决这个问题的地步;然而,我在这篇帖子中找到了有用的信息,解释了JSONP的作用。 - theabraham
在执行与上述相同的代码后出现了错误。SyntaxError:预期表达式,得到'<'。 - Debaprasad Jana
显示剩余9条评论

4
请尝试访问此网址:http://api.stackoverflow.com/1.1/stats?jsonp=callme
"callme" 是您的回调函数名称 - 在您的全局命名空间(window 对象)中。
顺便说一下,如果您使用 Firefox 并安装了 JSONView 插件,则可以直接测试上述网址(以及您自己的网址进行比较)。
调用该网址后的结果:
callme({
  "statistics": [
...
  ]
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接