雜談-JSONP探索

前言

平時工做當中,也已經好久沒有用JSONP 來跨域請求了,現從新整理一下,寫出本身對 JSONP 的理解。若是寫的有不對的,請各位看官評論指出,感謝。

行文時,系統環境爲 macOS Mojave v10.14.5,開發工具爲 vscode 1.45.1,瀏覽器爲 Goolge Chrome 版本 81.0.4044.138 。 javascript

JSONP是什麼

JSONP(JSON with Padding)是JSON的一種「使用模式」,可用於解決主流瀏覽器的跨域數據訪問的問題。html

這是引用了百度百科對 JSONP 的定義。筆者本身的理解是, JSONP 是一種利用瀏覽器 script 標籤的能力實現訪問跨域數據的小技巧。就是利用 script 標籤能訪問跨域資源的能力,利用 JSON 去填充返回內容,以達到跨域的目的。 前端

JSONP解決了什麼問題

上文說到了,JSONP 解決了跨域問題。那啥是跨域呢,簡單說就是發起請求的網站與被請求的網站,它倆的協議、主機、端口不是徹底同樣的。表現就是,跨域時,請求是不會成功的。
JSONP 究竟是怎麼實現的呢,筆者的理解是,基於下面三點實現的:java

  1. 瀏覽器的 script 標籤不受同源策略的限制,能夠請求到其它源的資源。
  2. script 標籤請求的資源拿到後,會被瀏覽器的 JS引擎 執行。
  3. script 請求到的資源是在 全局上下文 裏執行的。

JSONP測試

接下來就寫點代碼測試一下,並用大白話把過程描述一下。
用koa模擬服務端,代碼以下面試

const koa = require("koa");
const mount = require("koa-mount");
const app = new koa();
app.use(
  mount("/jsonp", (ctx) => {
    let callback = ctx.query.abc;
    let javascriptFileText = ` console.log(1); ${callback}("這是服務端的內容"); `;
    ctx.body = javascriptFileText;
  })
);
app.listen(8123);

複製代碼

前端代碼以下json

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>client</title>
</head>
<body>
    <script> function handler(res) { console.log(res) } window.addEventListener('load', () => { var url = 'http://127.0.0.1:8123/jsonp?abc=handler' var script = document.createElement('script'); script.src = url // 把script標籤塞入到文檔裏,就會發起請求 document.getElementsByTagName('head')[0].appendChild(script); }) </script>
</body>
</html>
複製代碼

筆者認爲的過程以下:跨域

  1. 服務端接收到 /jsonp這個路由的請求時(固然了,是get請求),就返回一段文本,內容是一個 console.log(1) 和一個函數調用,在這個調用裏傳入 "這是服務端的內容" 。對於服務端來講,這一段始終是字符串文本。
  2. _前端在把 script標籤塞入到文檔後,這個 script 就開始請求,請求拿到後是 console.log(1);handler("這是服務端的內容") 這樣的內容,而後瀏覽器 JS引擎 就把這段內容執行,能夠對應 eval() 理解。執行的時候,是處於 全局上下文 的。因此是能拿到 handler 這個函數的。而後呢,在 handler 裏就經過res拿到了服務端傳回給前端的內容。是否是很妙?!!我第一次用的時候,真的是眼前一亮,原來能夠這麼玩。
  3. 我這裏取名爲 abc 是爲了說明, JSONP 的使用不是說必定要寫成 xx/xx/xx?callback=xxx 的格式的,若是你和後臺同窗約定好了函數名字,你甚至能夠不用傳callback,直接寫成 xx/xx/xx 的接口請求就好了,功能是必定能實現的,只是可能你會被同事打而已。而且, handler 方法裏也不必定要傳 JSON 格式的內容,你也能夠寫成 handler(this) ,而後前端頁面裏拿到的就是 handler 函數執行上下文裏的 this 變量了,一樣,這樣寫沒有任何意義,只會被打而已。也能夠寫成 handler('name="服務端給的name"&age="服務端給的age"') ,這樣,經過 & 和 = 去切割獲取內容,這樣也很麻煩呀,因此最終你們都選擇傳 JSON 格式的內容,這是最方便獲取內容的方式。因此就叫 JSONP 。(這樣看來,是否是也能夠叫 callbackP 、 STRINGP 呢??)

後語

JSONP 這種技巧,如今(2020-06-01)已經不多有聽到有還在使用的。由於現代瀏覽器基本都支持了 CORS 標準,這可比只支持 GET 的 JSONP 強太多了。之後,筆者估計本身是不會用到 JSONP 了,這篇文章只是筆者看到有些公司在面試時,仍是會問 JSONP 的內容。因此就記錄一下。瀏覽器

相關文章
相關標籤/搜索