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了,没有作错误处理,也一时想不到什么错误处理,有人想到了能够告诉我一下。