手把手教你实现一个通用的jsonp跨域方法
什么是jsonp
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。
以上内容来自百度,不太理解不要紧,记住最重要的一点是:通过script标签引入的链接,接口返回的内容是被当成js代码来进行解析的。请大家记住这一点,很重要的特性。
创建一个简单的jsonp服务器
下面是一个基于nodejs的简单的服务器,如果不了解nodejs也没关系,大家看下注释,理解下作用就可以
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')
}
})
创建完服务器以后,我们接下来开始书写一个jsonp
/**
* @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: jsonp
来源:https://segmentfault.com/a/1190000015942144
手把手教你实现一个通用的jsonp跨域方法的更多相关文章
- Angular4 后台管理系统搭建(10) - 做一个通用的可跨域上传文件的组件
写的很慢,不知不觉这是第十篇了.但是我其他事情太多,只能抽空写下.现在angular4或angular2流行的上传方式是ng2-file-upload.它的功能很强大.但是我没有配置成可以跨域上传的. ...
- 深入剖析jsonp跨域原理
在项目中遇到一个jsonp跨域的问题,于是仔细的研究了一番jsonp跨域的原理.搞明白了一些以前不是很懂的地方,比如: 1)jsonp跨域只能是get请求,而不能是post请求: 2)jsonp跨域的 ...
- 只有20行Javascript代码!手把手教你写一个页面模板引擎
http://www.toobug.net/article/how_to_design_front_end_template_engine.html http://barretlee.com/webs ...
- iOS回顾笔记(05) -- 手把手教你封装一个广告轮播图框架
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...
- PWA入门:手把手教你制作一个PWA应用
摘要: PWA图文教程 原文:PWA入门:手把手教你制作一个PWA应用 作者:MudOnTire Fundebug经授权转载,版权归原作者所有. 简介 Web前端的同学是否想过学习app开发,以弥补自 ...
- R数据分析:跟随top期刊手把手教你做一个临床预测模型
临床预测模型也是大家比较感兴趣的,今天就带着大家看一篇临床预测模型的文章,并且用一个例子给大家过一遍做法. 这篇文章来自护理领域顶级期刊的文章,文章名在下面 Ballesta-Castillejos ...
- 关于前端jsonp跨域和一个简单的node服务搭建
先讲下概念 同源策略:是一种约定,浏览器最核心最基本的安全功能,(同域名,同协议,同端口)为同源 跨域: 跨(跳):范围 域 (源):域名,协议,端口 域名:ip的一种昵称(为了更好记住ip地址)如: ...
- jsonp跨域 封装通用方法
jsonp跨域 封装通用方法 //用法如下 jsonp({ url:"https://www.xxxx.com", params:{wd:'b'}, callback:'show' ...
- 通用jsonp跨域技术获取天气数据
1. 前言 在进行网站开发的过程中经常会用到第三方的数据,但是由于同源策略的限制导致ajax不能发送请求,因此也无法获得数据.解决ajax的跨域问题可以使用jsonp技术 2.代码 <!DOCT ...
随机推荐
- 百度编辑器上传视频以及视频编辑器预览bug解决
百度编辑器目前来讲是运用比较广泛的一个编辑器了,不仅开源还有中文的文档,所以很受欢迎,不过里面也有许多地方需要开发人员自己调试,其中一个比较常见的问题就是上传视频了,上传视频本身有一些小bug,这个基 ...
- PageHelper原理
1.要是用pagehelper,首先maven项目,要引入 <dependency> <groupId>com.github.pagehelper</groupId> ...
- Java基础——List集合整理(脑图,源码,面试题)
常在知乎牛客网关注Java的一些面试,了解过校招社招常面哪些内容.Java集合不仅使用频率高而且在初面中也常常被问到,何止是常常,关于ArrayList的扩容,HashMap的一些底层等等都被问到烂了 ...
- JS两个相同的字符串被判断为不相等问题
今天在写js的时候,遇到一个奇怪的问题,明明两个字符串相等,用alert()打印出来都一样,typeof的结果都是string, 仔细查看过了首尾都没有空格. 可是用a==b却判断为不相等 后来在网上 ...
- fileinput使用心得
下咋以及一些具体使用过程就不叙述了,简单说一下使用时候需要注意的几点 1.在js中封装好的fileinput函数 /* * 初始化fileInput控件(第一次初始化) * type 不同类别 * i ...
- 「EJOI2017」-骆驼
第一道构造题祭…… 文字叙述: 题目的提示很明显. $N$是$5$的倍数,所以考虑分成$5 \times 5$小块连在一起. 首先通过打表证明, 小块里从任何一点出发,经过所有的格,从任一一点跳出,一 ...
- notes 摘自陶哲轩演讲
摘自陶哲轩演讲http://www.youku.com/playlist_show/id_5267259.htmlA frog in a well 井底之蛙 Aristotle 亚里士多 ...
- 查看JDK的安装路径 和 安装版本
查看JDK的安装路径: 打开 运行,输入 cmd . 输入: java -verbose (ps:java后面必须敲一个空白格) 得到下图: 最后的两行, ...
- webServices学习四(---WebService监听工具)
之前我们使用过HttpWatch获取的HTTP的调用过程,并获得了HTTP的请求头及其他请求的详细信息. 既然WebServie也是通过HTTP进行通信的,能不使用HTTPWatch来获取它的请求过程 ...
- python 搜索匹配文件目录下所有的jpg或者png图片
import glob PATH_TO_TEST_IMAGES_DIR = 'D:\TrainChangeFifteenData\Picture\Test' for pidImage in glob. ...