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,而最後一個請求的回調卻處理了不是本身請求的內容。