jQuery的 jsonp 你们应该是十分熟悉了。php
曾遇到过这样的需求ajax
一、但愿请求几个类似的内容添加到页面json
二、请求的内容必定时间内是固定不变的,但愿作个缓存。缓存
因而脑子一拍写下了相似这样的代码 复制代码服务器
for(var i = 0; i < 3; i++){ $.ajax({ url:'.../return.php?num='+i, dataType: 'jsonp', jsonp: 'callback', jsonpCallback: 'dosome', cache: true }).done(function(re){ console.log(re); }).fail(function(){ console.log('fail'); }); }
复制代码函数
结果却老是只有一个成功并报错jsonp
Uncaught TypeError: dosome is not a functionurl
百思不得其解,不是有一个成功了吗?dosome怎么就不是函数了? 无奈之下花了大心思和时间在localhost上研究了jQuery的jsonp原理。code
设置服务器返回以下回调函数
<?php echo 'dosome("num='.$_GET['num'].'");'; ?>
获得返回以下
仔细翻看源码,在1.11.3版本发现
原来每次jsonp请求,jQuery都自动先把callbackName函数注册到window,又在返回后把window[ callbackName ]改回来。
因而同步执行完for循环发送请求后,处理第一个返回时就把window[ callbackName ]改为了 undefined,后续的返回都没法处理了。
我一阵郁闷,反正这个函数也没执行什么,不改回去不行吗?
惋惜,我仍是太天真,其实不改回去也同样没法正常获得想要的结果的。
我的理解,jQuery的jsonp原理大体以下
每次jsonp请求,都是新建一个处理函数把返回内容赋值到局部变量responseContainer,而后在调用注册的回调函数以对应的局部变量responseContainer[0]为参数执行。
当使用不一样的处理函数名时,一切相安无事(当咱们不写jsonpCallback时,jQuery会自动生成惟一不一样的函数名)。就如同上面的dosome1,2,3,各自引用并处理。
而使用一样的函数名时,循环时window['dosome']顺序被赋值,最终指向最后一个处理函数(如图中红线),其余的都被回收了。第一个返回时执行,把内容赋值到最后一个局部变量。
这样,第一个请求会拿不到返回内容从而fail,而最后一个请求的回调却处理了不是本身请求的内容。