天天看點

【JavaScript】通過封裝自己的JSONP解決浏覽器的跨域問題(Ajax跨域)

版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。更多學習資料請通路我愛科技論壇:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/82701029

問題引出:要發送Ajax請求,就必須使用HTTP請求?什麼是跨域問題?           

什麼是跨域問題:如果兩個頁面中的協定、域名、端口、子域名任意有一項不同,兩者之間所進行的通路行動就是跨域的,而浏覽器為了安全問題一般都限制了跨域通路,也就是不允許跨域請求資源。

如何解決呢?

1. 使用建立DOM元素的方式建立img對象, audio, video, link 這幾個對象都支援跨域請求,。           
var img = new Image();
    img.src = 'http://192.168.1.105:8080?name=zhangsan&age=18';           

類似于上面的這種呢?還有其他一些類似的标簽,實際上是可以向伺服器發送請求的,但是不能拿到傳回值

2.  使用link标簽, 但是也不能拿到伺服器的請求, 然後再試試script這個标簽來試試看???

<link rel="stylesheet" href="">           

link标簽隻能支援css的格式,其他格式的内容浏覽器是顯示不出來的

3. 使用script标簽來實作跨域, 也能滿足發送資料的要求, 接受資料呢?來測試一下。

var script = document.createElement('script');
    script.src = 'http://192.168.1.105:8080?name=zhangsan&age=18';
    document.body.appendChild(script);          // 開始正式發送請求           

經測試,還是真可以的,而且在用戶端也成功接受到了資料,這說明我們終于找對了路!

4. 解決沒有加載完成就輸出的問題( 這樣就會等待到script标簽加載完成之後執行)

// 在傳回資料到用戶端之前,先進行字元串拼接
    let json = JSON.stringify({
        id: 1,
        name: 'zhangsan',
        age: 18,
        gender: 'Male'
    });

    let jsonStr = 'var data = ' + json;           

上面的是我們伺服器的資料, 我們直接通過字元串拼接json,然後發給浏覽器。

console.log(data)           

直接輸出,我們發現報錯了,找不到這個變量???

原因是因為,浏覽器自上而下執行代碼,如果DOM元素沒有加載完畢就輸出,坑定會報錯的 

5.解決沒有加載完成就輸出的問題( 這樣就會等待到script标簽加載完成之後執行)           
script.addEventListener('load', function () {
        console.log(data);
    });           

直接綁定個事件不就行了,測試以後還真是可以。

但是,缺點是: 這種方式需要伺服器端定義一個全局變量, 進而會污染全局變量, 不太推薦…………

6. 上面的思路邏輯和代碼優化, 由于腳本執行過後才可以拿到資料, 上面的代碼可以優化嗎?           
var script = document.createElement('script');
    script.src = 'http://192.168.1.105:8080?name=zhangsan&age=18';
    document.body.appendChild(script);

    function callback(data) {
        console.log(data)
    }           

    實作原理: 伺服器端實際上是傳回了一個callback函數的調用, 類似于callback(jsondata), 是以當且僅當伺服器斷點資料傳回來以後, 下面的這個函數就相當于是自動調用了, 就會直接得到伺服器端傳回來的資料資訊, 進而列印輸出資料。

伺服器端就是這樣的:

let jsonFunc = `callback(${json})`;
           

7. 代碼的繼續優化, 可以直接在請求中, 我要自己定義一個函數呢?函數名我要自己指定的方法, 可以直接寫在url請求中。

var script1 = document.createElement('script');
    var url =  'http://192.168.1.105:8080?name=zhangsan&age=19&callback=callback1';
    script1.src = url;
    document.body.appendChild(script1);
    function callback1(data) {
        console.log(data);
    }           

伺服器端進行參數解析,換成使用者自己定義的函數名字不就行了?

let callback = urlObj.query.callback;

let jsonFunc = ''+callback+'' + '('+ json + ')';           

到此,浏覽器的跨域問題已經基本全部解決。

繼續閱讀