Fetch 提供了對
Request
和Response
(以及其餘與網絡請求有關的)對象通用的定義。它以後可以被使用到不少場景中:service workers、Cache API、其餘處理請求和響應的方式,甚至任何須要生成本身的響應的方式。javascript
衆所周知,fetch提供的請求資源的方法並不包括jsonp,可是咱們又想像使用fetch那樣使用jsonp方法該怎麼辦呢,本文就手把手教你實現一個本身的fetch jsonp方法。源碼在這裏.java
這裏就再也不累述jsonp的原理了,不懂得自行百度或者google吧。git
要本身書寫一個jsonp的方法,是要實現如下幾個模塊:github
生成script標籤json
註冊callback函數promise
返回一個Promise網絡
移除script標籤閉包
移除callback函數app
這一部分就直接生成手動操做dom實現就能夠,須要注意的是,爲了方便以後刪除這個script標籤,須要在建立的時候給這個標籤增長一個id屬性。具體代碼以下:dom
function createScript(_url, _id) { const script = document.createElement('script'); script.setAttribute('src', _url); script.id = _id; document.getElementsByTagName('head')[0].appendChild(script); }
註冊callback函數主要是給window添加一個屬性,這個屬性能夠什麼都不用幹,由於畢竟你只須要拿到他的參數,也就是請求的資源就能夠。這裏有一點須要注意就是爲了防止和window原本的屬性衝突,最好取個奇奇怪怪,隨機最好的名字。我取得名字就是jsonp123212這種。代碼以下:
function generateCB() { return `jsonp${Math.ceil(Math.random() * 1000000)}`; } window[cb] = (res) => { alert(res) //這裏的res就是你想請求的資源 }
這一部分是核心,只有成功的返回了一個promise纔能有機會像fetch那樣的形式去使用。實現的方法就是在callback函數中把返回的結果resolve出去。怎麼resolve出去?callback是全局的函數啊?這個時候就得想一想閉包了,它的存在就是結束這種坑爹的事情的,咱們只要在定時callback的時候讓他能訪問到resolve是否是就解決了呢?是的,具體作法,你看看:
function fetchJsonp(url) { return new Promise((resolve, reject)=>{ window[cb] = (res) => { resolve(res) } createScript() // 這裏就是生成script的函數 }) }
script標籤用過就不要再留着了,壞處一大堆,爲了優雅咱們就刪了他
function removeScipt(_id) { const script = document.getElementById(_id); document.getElementsByTagName('head')[0].removeChild(script); }
script你都移除了,cb更不能留着了啊,這個仍是個全局變量呢,因此刪。
function removeCB(_name) { delete window[_name]; }
到這裏都講完了,其實沒什麼難度,主要是本身項目中遇到了jsonp,可是fetch中沒有這個方法啊。因此就想着實現了一個,由於其餘的方法也都封裝,不差這一個了。完整的項目代碼在這裏。
還有須要補充的是我直接resolve了,沒有作錯誤處理,也一時想不到什麼錯誤處理,有人想到了能夠告訴我一下。