JS獲取本地數據:jsonp解決瀏覽器跨域問題

有時,頁面中有大量數據,而這些數據是靜態(tài)的,無需從后臺獲取。這時我們可能需要將這些數據單獨存放在一個json文件中,方便管理。
想到獲取數據,我第一個想到的就是使用ajax獲取數據。
來測試一下:

<script type="text/javascript">
    $(function () {
      $.ajax({
        type: 'get',
        url: './text.json',
        success: function (data) {
          console.log(data)
        }
      } )
    })
  </script>

在火狐瀏覽器運行成功獲取json數據如下圖。雖然提示“xml語法錯誤”,這個問題不影響程序運行,暫且不考慮。


火狐瀏覽器運行結果

在谷歌瀏覽器中運行,竟然不能獲取數據。這就奇怪了,同樣的代碼在谷歌瀏覽器里執(zhí)行不下去了。


谷歌瀏覽器運行結果

通過在火狐瀏覽器能運行成功,可得知這段代碼本身沒有錯誤,查看錯誤提示信息,原來是請求出現了跨域。
就這個問題來一探究竟···

那么為什么會出現跨域問題呢?

要回答跨域問題,首先要弄清楚什么是瀏覽器的同源策略。

協議、域名、端口相同視為統(tǒng)一域,一個域內的腳本只有本域有權訪問??梢岳斫鉃椋居騼鹊哪_本只有讀寫本域內的資源,而無法訪問其他域內的資源。這種安全稱為同源策略。
同源策略保證了資源的隔離。一個網站的腳本只能方位自己的資源,就想操作系統(tǒng)里的進程不能訪問另一個進程的資源一樣。如果沒有同源策略,你在網站瀏覽,跳轉其他網頁,然后這個網頁就可以跨域讀取你網站的信息,這樣整個web世界就沒有隱私可言了。這就是同源策略的重要性,他限制了這些行動。當然在同一個域內,客戶端腳本可以任意讀取同源內的資源,前提是這個資源本身是可讀可寫的。

回答完瀏覽器的同源策略再來說什么是跨域。

只要協議、域名、端口有一個不同就是跨域
ajax請求一個非本域的web資源就是跨域

接下來說說為什么谷歌提示跨域而火狐沒有提示

谷歌瀏覽器既然找不到資源,肯定是出現了跨域問題,那么一定是協議、域名或者端口有一個不統(tǒng)一。
這里要提一點,訪問本地計算機里的文件,使用的是file協議(file協議主要用于訪問本地資源)
這樣的話谷歌報錯是有理有據的。
在看控制臺提示
Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

跨源請求僅支持協議方案。 :http, data, chrome, chrome-extension, https.
說白了就是,由于安全原因瀏覽器不允許跨域訪問,安全機制認為加載本地其他文件是跨域行為。谷歌瀏覽器會跨域失敗,是因為瀏覽器安全機制不允許,而火狐為了方便允許跨域(雖然這樣很不安全)。而且在其他瀏覽器中,出現跨域問題也是這個原因,就是瀏覽器安全機制的原因。

為什么谷歌不支持跨域?

這是因為瀏覽器的安全策略,即禁止ajax訪問本地的文件,這是不安全也是不允許的,舉例的話,就相當于你訪問了一個網站,然后這個網站就可 以讀取到你本地的文件,這種行為是不允許的。

怎么解決跨域問題?

1、前端人員使用的一般是JSONP進行跨域。
2、項目中使用nginx反向代理。
3、修改谷歌瀏覽器的配置。
4、在webstrom中打開。
這四種方法,前端人員本地最方便也是最實用的就是第一種,不建議使用第三種方法,你修改了瀏覽器的配置,難道讓用戶也修改瀏覽器的配置嗎。
第二種方法,在項目中,會部署 nginx 反向代理,這里不做具體贅述。有需要的可以自行查找。
第四種方法,用在angula的路由中,webstrom中自帶了一個本地服務器。會自動為你的文件開一個端口服務。

使用jsonp解決跨域(僅適用于get請求)

實現原理<script>標簽是不接受同源策略的他可以載入任意地方的JavaScript文件,而并不要求同源。所以jsonp的理念就是,我和服務端約定好一個函數名,當我請求文件的時候,服務端返回一段JavaScript,這段JavaScript調用了我們約定好的函數,并且將數據當做參數傳入。非常巧合的一點,json的數據格式和JavaScript語言中的對象格式正好相同。所以我們約定好的函數里可以直接使用這個對象。
代碼:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="../jquery-1.10.2.min.js"></script>
  <title>Document</title>
</head>
<body>
  <script type="text/javascript">
    function dataInit(data){
      console.log(data)
    }
  </script>
  <script type="text/javascript" src="./text.json?callback=dataInit"></script>
//值得注意的是
// src ? 之前為文件地址,? 之后為回調函數callback名稱,    
//回調函數可以簡寫為 cb ,  然后 回調函數 名稱要與  JSON文件中的名稱一致 
</body>
</html>

json文件 text.json
dataInit([{
    "name": "zangsan",
    "sex": "6"
  },
  {
    "name": "李四",
    "sex": "8"
  }
])

為什么可以這樣寫的原因:
function dataInit(data){
console.log(data)
}
這里先定義了一個函數,用于輸出數據data;
<script type="text/javascript" src="./text.json?callback=dataInit"></script>
當通過script標簽成功獲得text.json文件時,瀏覽器立即執(zhí)行文件中的內容。text.json文件中本質是調用這個函數并傳入數據。
這樣就解釋清楚了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容