天天看點

jsonp的原理介紹及Promise封裝 javascript

什麼是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的原理介紹及Promise封裝 javascript

參數介紹

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)
}
           
vue