JSONP(JSON with Padding)是JSON的一種「使用模式」,可用於解決主流瀏覽器的跨域數據訪問的問題。因爲同源策略,通常來講位於 server1.example.com 的網頁沒法與不是 server1.example.com的服務器溝通,而 HTML 的<script> 元素是一個例外。利用 <script> 元素的這個開放策略,網頁能夠獲得從其餘來源動態產生的 JSON 資料,而這種使用模式就是所謂的 JSONP。用 JSONP 抓到的資料並非 JSON,而是任意的JavaScript,用 JavaScript 直譯器執行而不是用 JSON 解析器解析。前端
以上內容來自百度,不太理解沒關係,記住最重要的一點是:經過script標籤引入的連接,接口返回的內容是被當成js代碼來進行解析的。請你們記住這一點,很重要的特性。node
下面是一個基於nodejs的簡單的服務器,若是不瞭解nodejs也不要緊,你們看下注釋,理解下做用就能夠git
const http = require('http') const url = require('url') const jsonpServer = http.createServer((req, res) => { let data = { status: true, msg: 'hello jsonp' } const body = url.parse(req.url, true) // jsonp請求中會包含一個callback參數,例如 http://baidu.com.js?callback=hello // 獲取請求的url中的callback參數的值,callback是一個函數名 const callback = body.query.callback // 將對象數據轉爲字符串 data = JSON.stringify(data) // 拼接成js代碼 // 舉個例子,假設這個callback回調的名字是 test // 拼接完就是 test({status: true,msg: 'hello jsonp'}) // 顯然,就是一段js代碼,做用就是執行這個函數 const js = `${callback}(${data})` // 返回js代碼給客戶端 res.end(js) }) jsonpServer.listen('3000', (err) => { if (!err) { console.log('server is running at localhost:3000') } })
/** * @description 建立一個隨機的函數名 * @return {string} */ const createCallbackName = function () { return `callback${(Math.random() * 1000000).toFixed(0)}` } /** * @description 插入一個script標籤 * @param url {string} */ const insertScript = function (url) { let script = document.createElement('script') script.onload = script.onerror = function () { document.body.removeChild(script) } script.setAttribute('src', url) document.body.appendChild(script) } /** * @description 拼接字符串參數 * @param url {string} url * @param data {object} 要拼接的query數據 * @return url {string} 拼接完成後的新url */ const setQuery = function (url, data) { const keys = Object.keys(data) if (keys.length === 0) { return url } else{ const pairs = keys.map(key => `${key}=${data[key]}`) url = url.includes('?') ? url : `${url}?` url += pairs.join('&') return url } } /** * @description jsonp函數 * @param url {string} 請求地址 * @param config {object} 接口配置設置 * @return {Promise} */ const jsonp = function (url, config = {}) { let data = config.data || {} let timeout = config.timeout || 5000 let timer const funcName = createCallbackName() data.callback = funcName return new Promise((resolve, reject) => { window[funcName] = function (res) { if (timer) { clearTimeout(timer) } delete window[funcName] resolve(res) } url = setQuery(url, data) timer = setTimeout(() => { delete window[funcName] reject(new Error(`fetch ${url} fail`)) }, timeout) insertScript(url) }) } // 使用效果 jsonp('http://localhost:3000') .then(res => { console.log(res) }) .catch(err => { console.log(err) })
獲取更多知識,請微信掃碼關注公衆號關注早讀君,天天早晨爲你推送前端知識,度過擠地鐵坐公交的時光。
並且不定時舉辦活動贈送書籍哦github