jQuery getJSON 回调不工作 - 即使有有效的 JSON - 似乎使用 "OPTION" 请求而不是 "GET
背景是我有一个用Django配置的分布式任务服务器,使用celery来处理任务,这个服务器可以返回正在运行的任务状态,格式是JSON。这个任务服务器的地址是celeryserver.mydomain.com,而我执行jQuery的页面是在www.mydomain.com,所以我应该不需要考虑JSONP,因为请求并不是发往不同的域名,对吧?
从我的服务器日志来看,我看到jQuery每3秒执行一次getJSON
调用,这个是正常的(因为有JavaScript的setInterval)。确实它会使用一个OPTION请求,但我用curl
确认过,这种请求类型依然能返回JSON数据。
问题是,下面jQuery中的console.log()
调用似乎从来没有执行过!在getJSON
调用之前的那个是执行了的。没有回调函数正常工作对我来说是个问题,因为我希望通过这种方式来轮询celery任务的状态,并根据任务的状态做不同的事情。
<script type="text/javascript">
var job_id = 'a8f25420-1faf-4084-bf45-fe3f82200ccb';
// wait for the DOM to be loaded then start polling for conversion status
$(document).ready(function() {
var getConvertStatus = function(){
console.log('getting some status');
$.getJSON("https://celeryserver.mydomain.com/done/" + job_id,
function(data){
console.log('callback works');
});
}
setInterval(getConvertStatus, 3000);
});
</script>
我用curl
确认了我从服务器收到的内容:
$ curl -D - -k -X GET https://celeryserver.mydomain.com/done/a8f25420-1faf-4084-bf45-fe3f82200ccb
HTTP/1.1 200 OK
Server: nginx/0.6.35
Date: Mon, 27 Jul 2009 06:08:42 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: close
{"task": {"executed": true, "id": "a8f25420-1faf-4084-bf45-fe3f82200ccb"}}
我觉得那个JSON看起来没问题,JSONlint.com现在也帮我验证过了……我还用-X OPTION
模拟了jQuery的查询,结果从服务器返回的数据和用GET请求得到的完全一样(内容类型是application/json等等)。
我盯着这个问题看了很久,非常感谢任何帮助。我是个比较新的jQuery用户,但这看起来应该没有问题,所以我不知道我哪里出错了!
4 个回答
正如很多人提到的,子域名也算作独立的域名,所以我遇到了跨域的问题 :)
我通过创建一个小的Django中间件解决了这个问题。这个中间件会检查我的视图返回的内容,如果是JSON格式并且请求中有回调函数,它就会对响应进行一些修改。
class JSONPMiddleware:
def process_response(self, request, response):
ctype = response.get('content-type', None)
cback = request.GET.get('callback', None)
if ctype == 'application/json' and cback:
jsonp = '{callback}({json})'.format(callback=cback, json=response.content)
return HttpResponse(content=jsonp, mimetype='application/javascript')
return response
现在一切都按计划进行,感谢大家!
把你的网址改成这样:
"https://celeryserver.mydomain.com/done/" + job_id + "?callback=?"
然后在你的 Django 视图中,结果应该类似于:
'{callback}({json})'.format(callback=request.GET['callback'], json=MyJSON)
...其实有很多方法可以实现最后那一行,但基本上就是读取回调参数(你可以随便给它起个名字)
然后把它作为调用你的 JSON 对象返回(jQuery 会自动处理创建回调函数,它会把 '?' 替换成生成的函数)
我觉得你遇到了跨子域的问题,sub.domain.tld
和 domain.ltd
不是同一个东西。
我建议你安装一下 Firebug,看看你的代码在请求开始时是否出现了 权限被拒绝 的错误。如果是这样的话,可以考虑使用 JSONP...