1. 程式人生 > >javascript跨域獲取json資料

javascript跨域獲取json資料

專案在開發過程中,用到了天氣預報的功能,所以需要呼叫天氣預報的api,一開始以為直接用ajax呼叫url就可以獲取天氣資料,結果涉及到了跨域的問題,這裡做一個記錄。

說到跨域,就得知道同源策略

同源策略(Same origin policy),是由Netscape提出的一個著名的安全策略。現在所有支援JavaScript 的瀏覽器都會使用這個策略。所謂同源是指,域名,協議,埠相同。它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。可以說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。 同源策略就是指頁面上的指令碼不能訪問非同源的資源(包括HTTP響應和Cookie) 

跨域(Cross-Domain ):違反了同源策略,即域名、協議、埠不完全相同時,js不能進行行資料傳輸或通訊。

跨域的錯誤提示:Origin XX is not allowed by Access-Control-Allow-Origin錯誤原因:

解決跨域的方法:

1. 通過jsonp實現跨域

雖然瀏覽器預設禁止了跨域訪問,但並不禁止在頁面中引用其他域的JS檔案(不僅如此,我們還發現凡是擁有"src"這個屬性的標籤都擁有跨域的能力,比如<script>、<img>、<iframe>),並可以自由執行引入的JS檔案中的function(包括操作cookie、Dom等等)。根據這一點,可以方便地通過建立script節點的方法來實現完全跨域的通訊。jsonp正是利用這個特性來實現的。

我的天氣預報的資料來源api是百度api store提供的,返回的資料是json格式。天氣資訊是根據登陸使用者的資訊變化的,所以在新增script的節點需要動態新增。

這裡有個問題:動態新增的script節點如何銷燬?

jQuery的ajax實現跨域

由於專案用到了jQuery框架,所以直接用jQuery的ajax或者getJSON來實現跨域。根據jQuery的api介紹(http://api.jquery.com/jQuery.getJSON/#urldatacallback),getJSON只是Query的ajax的一種簡化寫法。利用jQuery的ajax實現跨域和自己新增script的原理是一樣的,只不過我們不需要手動的插入script標籤以及定義回撥函式。jquery會自動生成一個全域性函式來替換callback=?中的問號,之後獲取到資料後又會自動銷燬,實際上就是起一個臨時代理函式的作用。$.getJSON方法會自動判斷是否跨域,不跨域的話,就呼叫普通的ajax方法;跨域的話,則會以非同步載入js檔案的形式來呼叫jsonp的回撥函式。參考:http://www.cnblogs.com/know/archive/2011/10/09/2204005.html

   $.ajax({
                type: "GET",
                url: "http://api.duoshuo.com/threads/counts.jsonp?short_name=official&threads=4ff1cbc43ae636b72a00001d",
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert(textStatus);
                    alert(errorThrown);
                    this; // 呼叫本次AJAX請求時傳遞的options引數
                },
                dataType: "jsonp",
                success: function (msg, textStatus) {
					alert(‘ok‘)
					}
			})

  百度apistore中的天氣api並支援jsonp,所以,當我採用上述方式請求資料時,返回的資料依然是json,而不是 回撥函式(json)的格式,所以無法執行回撥函式,此時的錯誤提示為:Uncaught syntax Error: unexpected token:……,這是因為伺服器返回來json資料後直接放入了script標籤,等script標籤載入完後,會立即把響應的json當js去執行,很明顯{"errNum":0,"errMsg":"success","retData":{"city":"\u5317\u4eac","pinyin":"beijing","citycode":"101010100","date":"15-03-03","time":"08:00","postCode":"100000","longitude":116.391,"latitude":39.904,"altitude":"33","weather":"\u6674","temp":"4","l_tmp":"-4","h_tmp":"4","WD":"\u5317\u98ce","WS":"5-6\u7ea7(25~34m\/h)","sunrise":"06:45","sunset":"18:07"}}不是合法的js語句,錯誤出現報錯

2.使用HTML5 postMessage

未完待續

參考文獻: