聊一聊JSONP和影像Ping的區別

JSONP

在講 JSONP 之前需要再來回顧一下在頁面上使用 script 引入外部的 js 文件時到底引入了什麼?

先建立一個 index.js 文件。

console.log(123)

再建立一個 index.html 文件。

<!DOCTYPE html>
<html lang='en'>
  <head>
    <meta charset='utf-8'>
    <title>JSONP</title>
  </head>
  <body>
    <script src='index.js'></script>
  </body>
</html>

上面的

<script src='index.js'></script>

等價於

<script>
	console.log(123)  
</script>

現在再來看 JSONP 就比較好理解了。

假設我現在需要向 www.abc.com 上請求一個資源 asset。我需要先創建一個 script 標籤令其 src 等於這個源來訪問這個資源

<script src= '//www.abc.com/?dataName=asset&callback=handleResponse'></script>

根據上面的舉例我們知道 script 返回的就是一段 JS 程式碼,那麼伺服器在接收到我們的請求時,如果給我們返回一段 JS 程式碼,這段程式碼可以是一個函數執行的程式碼,而且函數的參數可以就是我們請求的資源。

例如上面的 handleResponse 函數在本地的定義如下:

handleResponse(asset) {
  console.log('從服務端得到的資源 asset 為', asset)
}

服務端給我們返回的 JS 程式碼如下:

handleResponse(asset)

在script 標籤就相當於

<sctript>
  handleResponse(asset)
</sctript>

handleResponse 在本地又有定義,服務端的資源 asset 也通過函數參數的形式傳遞下來了。

由於 asset 的形式往往是 JSON 的格式,所以這種跨域的方式被稱為 JSONP。

JSONP 由兩部分構成,

  • 參數(JSON格式,就是服務端需要傳遞給客戶端的數據

  • 回調函數

    名字要和瀏覽器端程式碼中定義的名字相同,在上面的例子中瀏覽器端定義的是 handleResponse,在服務端返回的函數名字也應該是 handleResponse,只有這樣在瀏覽器端接收到後才能進行調用。

影像 Ping

我們知道使用 script 標籤返回的是一段 JS 程式碼,請問下面這段程式碼返回的是什麼。

<img src='//www.abc.com/?dataName=img1'>

往往返回的是一張圖片,因此瀏覽器端是沒有辦法接收到服務端的返回值的。

雖然它不像 JSONP 使用那麼廣泛,但是還是有一定的用武之地的。

例如用於統計某個廣告的點擊次數,創建一個 img 標籤,然後綁定一個 click 事件,當點擊圖片時給 img.src 賦值,這個時候就會向 '//www.abc.com/count' 發送請求,服務端在接收到這個請求之後就可以令點擊次數加 1.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <script>
    const img = document.createElement('img')
    img.onclick = function () {
      img.src='//www.abc.com/count'
    }
    document.appendChild(img)
  </script>
</body>
</html>

注意這個例子並不嚴謹,這裡主要是說明統計點擊某個廣告次數的思路,使用影像 Ping 是可以實現的。