例如,我有以下JavaScript代码(已加载Dojo 1.6):
dojo.require("dojo.io.script") // PART I var jsonpArgs = { url: "http://myapp.appspot.com/query", content: { id: "1234", name: "Juan", start_date: "2000-01-01", callback: "recover" } }; // PART II dojo.io.script.get(jsonpArgs).then(function(data) { console.log(data); }); // PART III function recover(data) { console.log(data); }
从浏览器直接查询
我知道我的服务器将收到查询,就像我在地址栏中键入以下内容一样:
http://myapp.appspot.com/query?id=1234&name=Juan&start_date=2000-01-01&callback=recover
预期的回应
如果我使用浏览器地址栏直接查询我的服务器,我会收到MIME类型application / json和浏览器中呈现的明文,如下所示:
recover( { id: 1234, name: Juan, data: [ ["2000-01-01", 1234], ["2000-01-02", 5678] ] } );
问题
现在,回顾JavaScript的第二部分,我将使用dojo.io.script.get(jsonpArgs)执行JSONP请求.这将返回一个Deferred对象,我可以通过链接来利用它.然后再使用它.请注意,我为.then事件定义了处理程序,以将捕获的数据输出到控制台.
但是,我在控制台中获得的只是一个事件.我试图搜索它的数据树,但我找不到我预期的数据.
题
>存储JSONP请求的响应在哪里?我怎么找到它?
>我的服务器(我控制)只输出请求数据的明文呈现,包装在回调函数(此处指定为recover)中,并指定application / json MIME类型.我需要在我的服务器上设置任何其他内容,以便Deferred对象捕获响应数据吗?
试图解决方案
我实际上可以通过定义回调函数来恢复响应(在本例中,在JavaScript的第三部分中进行恢复).但是,在Dojo教程中,他们只是使用Deferred(和.then)框架恢复了数据.我如何使用Dojo Deferreds做到这一点?
更新(使用Dojo教程中的Twitter示例)
以Dojo教程Getting Jiggy With JSONP中的这个脚本为例.我编辑它以将数据记录到控制台.
dojo.require("dojo.io.script"); dojo.io.script.get({ url: "http://search.twitter.com/search.json", callbackParamName: "callback", content: {q: "#dojo"} }).then(function(data){ //we're only interested in data.results, so strip it off and return it console.log(data); // I get an Object, not an Event, but no Twitter data when browsing the results property console.log(data.results) // I get an array of Objects return data.results; });
对于console.log(数据),我得到一个Object,而不是我的情况所示的事件.由于该示例暗示数据驻留在data.results中,我还尝试浏览此树,但我没有看到来自Twitter的预期数据.我不知所措.
对于console.log(data.results),我得到一个Objects数组.如果我直接查询Twitter,这就是我用明文得到的.每个对象都包含通常的推文元数据,如用户名,时间,用户肖像和推文本身.很容易.
这个击中了我的头部. .then链的处理程序,一个匿名函数,只接收一个参数数据.但是为什么console.log(data)中的results属性和我从console.log(data.results)获得的返回对象是不同的?
我知道了.手动回调实现
function recover(data) { console.log(data); } var jsonpArgs = { url: "http://myapp.appspot.com/query", content: { id: "1234", name: "Juan", start_date: "2000-01-01", callback: "recover" }; dojo.io.script.get(jsonpArgs);
这是我的服务器将收到的请求:
http://myapp.appspot.com/query?id=1234&name=Juan&start_date=2000-01-01&callback=recover
在这种情况下,我希望我的服务器输出以下内容:
recover({ id: 1234, name: Juan, data: [ ["2000-01-01", 1234], ["2000-01-02", 5678] ] });
需要注意三点:
>服务器将在查询URL字符串中期望回调.回调是作为jsonpArgs的属性实现的.
>因为我指定了callback = recover,我的服务器将附加recover(the_data_I_need),将整个字符串返回给浏览器,浏览器将执行recover(the_data_I_need).这意味着…
>我必须定义,例如,函数recover(one_argument_only){doAnythingYouWantWith(one_argument_only)}
这种方法的问题是我不能利用.then的Deferred链接.例如:
dojo.io.script.get(jsonpArgs).then(function(response_from_server) { console.log(response_from_server); })
这将给我一个事件,根本没有预期的响应痕迹.
利用Dojo实现的JSONP请求
var jsonpArgs = { url: "http://myapp.appspot.com/query", callbackParamName: "callback", content: { id: "1234", name: "Juan", start_date: "2000-01-01" }; dojo.io.script.get(jsonpArgs);
这是我的服务器将收到的请求:
http://myapp.appspot.com/query?id=1234&name=Juan&start_date=2000-01-01&callback=some_function_name_generated_by_dojo
在这种情况下,我希望我的服务器输出以下内容:
some_function_name_generated_by_dojo({ id: 1234, name: Juan, data: [ ["2000-01-01", 1234], ["2000-01-02", 5678] ] });
注意事项:
>注意jsonpArgs的属性,callbackParamName.此属性的值必须是服务器期望的变量(在查询URL字符串中)的名称.如果我的服务器需要callbackfoo,那么callbackParamName:“callbackfoo”.在我的情况下,我的服务器期望名称回调,因此callbackParamName:“回调”.
>在前面的示例中,我在查询URL中指定了callback = recover并继续实现函数recover(…){…}.这次,我不需要担心. Dojo将插入自己的首选函数callback = some_function_name_generated_by_dojo.
>我想some_function_name_generated_by_dojo定义为:
定义:
function some_function_name_generated_by_dojo(response_from_server) { return response_from_server; }
当然,定义并不那么简单,但这种方法的优点是我可以利用Dojo的Deferred框架.请参阅下面的代码,它与前面的示例相同:
dojo.io.script.get(jsonpArgs).then(function(response_from_server) { console.log(response_from_server); })
这将为我提供我需要的确切数据:
{ id: 1234, name: Juan, data: [ ["2000-01-01", 1234], ["2000-01-02", 5678] ] }