什麼是jsonp :
Jsonp(JSON with Padding) 是 json 的一種"使用模式",可以讓網頁從别的域名(網站)那擷取資料,即跨域讀取資料。
為什麼我們從不同的域(網站)通路資料需要一個特殊的技術( JSONP )呢?這是因為同源政策。
同源政策,它是由 Netscape 提出的一個著名的安全政策,現在所有支援 JavaScript 的浏覽器都會使用這個政策。
jsonp的實作原理:
動态建立script标簽,因為script标簽是沒有同源政策限制,可以跨域的。 把script标簽的src指向正式服務端位址,這個位址跟個參數callback=xxx, 服務端在傳回資料時,在xxx裡包裹一個方法(裡面是傳回的資料),相當于在前端執行xxx這個方法,但是浏覽器并沒有這個方法,是以在發送請求之前在window注冊這個方法,這樣的話相當于在前端執行window.xxx()這個方法去擷取資料。 具體看接下來的實作!
想看jsonp具體實作的可看官網位址:jsonp git位址
介紹:
參數介紹
jsonp(url, opts, fn)
-
url (String) 伺服器端資料接口位址
opts (Object) 一般隻需關注param即可
- param (String) 預設是callback,這是與後端約定的參數名稱,也可以随便定義,隻要前後端統一
- timeout (Number) 請求逾時時間,預設是6000ms
- prefix (String) callback值的字首,預設是__jp
- name (String) 指定全局注冊的回調方法名,一般不會用到,因為預設是prefix+自增數字
fn 回調方法,用es6 Promise
使用方法
步驟一、
首先安裝這個庫,因為我是在node npm環境下開發,是以
$ npm install jsonp
步驟二、
下面是具體用法:
建一個名叫jsonp.js的檔案
先引入jsonp庫檔案
對外暴露方法 url:請求伺服器位址,data:參數
export default function jsonp(url,data,option) {
url += (url.indexOf('?')<0?'?':'&')+param(data)
return new Promise(function(resolve,reject) {
originJSONP(url,option, function(err,data) {
if(!err){
resolve(data)
}else{
reject(err)
}
})
})
}
定義一個将Object的參數處理成為 url挂載參數的形式 的函數
export function param(data) {
let url = ''
for (var k in data) {
let value = data[k] !== undefined ? data[k] : ''
url += '&' + k + '=' + encodeURIComponent(value)
}
return url ? url.substring(1) : ''
}
到這裡 這個Promise 就封裝好了,接下來就具體調用來擷取資料
完整的jsonp.js檔案:
//jsonp.js檔案
import originJsonp from 'jsonp' //首先引入jsonp
//第一個參數url為接口位址。
// 第二個參數data為接口位址後面攜帶的參數。因為jsonp不支援直接傳一個對象。是以,我們可以把url和需要傳的參數分開。這樣我們調用這個方法的時候會更加友善。
// 第三個參數opts為對應api上面的opts
export default function jsonp(url, data, opts) {
//拼接url和需要傳遞的參數data。
//先判斷url後面有沒有?号,沒有的話後面加?,有的話後面加&
url += (url.indexOf("?") < 0 ? "?" : "&") + param(data);
//jsonp的函數我們需要傳回一個promise
return new Promise((resolve, reject) => {
originJsonp(url, opts, (err, data) => {
if (!err) {
resolve(data)
} else {
reject(err)
}
})
})
}
//封裝一個方法,把對象拆解出來拼接到url的後面
export function param(data) {
let url = "";
for (var k in data) {
//如果data[k]為undefined的話,就傳回空
let value = data[k] !== undefined ? data[k] : "";
//我們使用 encodeURIComponent() 對 URI 進行一下編碼
url += `&${k}=${encodeURIComponent(value)}`;
}
//如果url不為空的話需要删去第一個&。
return url ? url.substring(1) : "";
}
步驟三、
建一個js檔案,名字自己定義
引入前面封裝的jsonp.js
定義參數
const commonParams = {
g_tk:1319877694,
inCharset:'utf-8',
outCharset:'utf-8',
notice:0,
format:'jsonp'
};
定義前後端統一參數
const options = {
param:'jsonpCallback'
};
定義擷取資料函數 這裡我是拿QQ音樂的資料https://m.y.qq.com/
export function getDataFunc() {
const url = 'https://c.y.qq.com/musichall/fcgi-bin/fcg_yqqhomepagerecommend.fcg'
const data = Object.assign({},commonParams,{
platform:'h5',
uin:0,
needNewCode:1,
})
return jsonp(url,data,options)
}