深入源碼分析使用jQuery連續發起jsonp請求失敗的原因


jQuery的 jsonp 大家應該是十分熟悉了。
曾遇到過這樣的需求
1、希望請求幾個相似的內容添加到頁面
2、請求的內容一定時間內是固定不變的,希望做個緩存。

於是腦子一拍寫下了類似這樣的代碼

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');
    });
}

結果卻總是只有一個成功並報錯

Uncaught TypeError: dosome is not a function

百思不得其解,不是有一個成功了嗎?dosome怎么就不是函數了?
無奈之下花了大心思和時間在localhost上研究了jQuery的jsonp原理。

設置服務器返回如下

<?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,而最后一個請求的回調卻處理了不是自己請求的內容。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM