什么是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) =&gt; {
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) =&gt; {
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 =&gt; `${key}=${data[key]}`)
url = url.includes('?') ? url : `${url}?`
url += pairs.join('&amp;')
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) =&gt; {
window[funcName] = function (res) {
if (timer) {
clearTimeout(timer)
}
delete window[funcName]
resolve(res)
}
url = setQuery(url, data)
timer = setTimeout(() =&gt; {
delete window[funcName]
reject(new Error(`fetch ${url} fail`))
}, timeout)
insertScript(url)
})
}
// 使用效果
jsonp('http://localhost:3000')
.then(res =&gt; {
console.log(res)
})
.catch(err =&gt; {
console.log(err)
})

项目演示地址请查看github: jsonp

来源:https://segmentfault.com/a/1190000015942144

手把手教你实现一个通用的jsonp跨域方法的更多相关文章

  1. Angular4 后台管理系统搭建(10) - 做一个通用的可跨域上传文件的组件

    写的很慢,不知不觉这是第十篇了.但是我其他事情太多,只能抽空写下.现在angular4或angular2流行的上传方式是ng2-file-upload.它的功能很强大.但是我没有配置成可以跨域上传的. ...

  2. 深入剖析jsonp跨域原理

    在项目中遇到一个jsonp跨域的问题,于是仔细的研究了一番jsonp跨域的原理.搞明白了一些以前不是很懂的地方,比如: 1)jsonp跨域只能是get请求,而不能是post请求: 2)jsonp跨域的 ...

  3. 只有20行Javascript代码!手把手教你写一个页面模板引擎

    http://www.toobug.net/article/how_to_design_front_end_template_engine.html http://barretlee.com/webs ...

  4. iOS回顾笔记(05) -- 手把手教你封装一个广告轮播图框架

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  5. PWA入门:手把手教你制作一个PWA应用

    摘要: PWA图文教程 原文:PWA入门:手把手教你制作一个PWA应用 作者:MudOnTire Fundebug经授权转载,版权归原作者所有. 简介 Web前端的同学是否想过学习app开发,以弥补自 ...

  6. R数据分析:跟随top期刊手把手教你做一个临床预测模型

    临床预测模型也是大家比较感兴趣的,今天就带着大家看一篇临床预测模型的文章,并且用一个例子给大家过一遍做法. 这篇文章来自护理领域顶级期刊的文章,文章名在下面 Ballesta-Castillejos ...

  7. 关于前端jsonp跨域和一个简单的node服务搭建

    先讲下概念 同源策略:是一种约定,浏览器最核心最基本的安全功能,(同域名,同协议,同端口)为同源 跨域: 跨(跳):范围 域 (源):域名,协议,端口 域名:ip的一种昵称(为了更好记住ip地址)如: ...

  8. jsonp跨域 封装通用方法

    jsonp跨域 封装通用方法 //用法如下 jsonp({ url:"https://www.xxxx.com", params:{wd:'b'}, callback:'show' ...

  9. 通用jsonp跨域技术获取天气数据

    1. 前言 在进行网站开发的过程中经常会用到第三方的数据,但是由于同源策略的限制导致ajax不能发送请求,因此也无法获得数据.解决ajax的跨域问题可以使用jsonp技术 2.代码 <!DOCT ...

随机推荐

  1. Odoo的权限

    Odoo的权限的核心是权限组(res_groups).对每个权限组,可以设置权限组的菜单表示,对象表示,记录规则表示,字段表示. 1.菜单/对象级别 设置哪些人可以访问哪些菜单/对象,对象的访问权限包 ...

  2. 廖雪峰Java11多线程编程-2线程同步-1同步代码块

    1.线程安全问题 多个线程同时运行,线程调度由操作系统决定,程序本身无法决定 如果多个线程同时读写共享变量,就可能出现问题 class AddThread extends Thread{ public ...

  3. Python Flask学习之安装SQL,python3,Pycharm(网上下载安装即可)

    1,下载时更改pypi源.可以额外安装虚拟化环境:pip install -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.co ...

  4. zepto.js按需载入模板对象

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/Joyhen/article/details/34412103 Zepto.js 是支持移动WebKi ...

  5. 一些hbase的shell查询语句

    华为bids(不想吐槽)种种原因只能用hbase shell查询,在此记录下自己探索的hbase shell 免得下次要用还得去找 scan 'ogg_sel_ioc_sv_product_name_ ...

  6. hbase连接linux开发过程

    最近近公司被安排做hbase开发,太久没做今天记录下过程 import java.io.IOException; import org.apache.hadoop.conf.Configuration ...

  7. LINUX对于未安装的软件包的查看

    查看的前提是您有一个.rpm 的文件,也就是说对既有软件file.rpm的查看等: 1.查看一个软件包的用途.版本等信息: 语法: rpm -qpi file.rpm 举例: [root@localh ...

  8. Leetcode458.Poor Pigs可怜的小猪

    有1000只水桶,其中有且只有一桶装的含有毒药,其余装的都是水.它们从外观看起来都一样.如果小猪喝了毒药,它会在15分钟内死去. 问题来了,如果需要你在一小时内,弄清楚哪只水桶含有毒药,你最少需要多少 ...

  9. CENTOS 7更换系统启动默认内核

    本文不再更新,可能存在内容过时的情况,实时更新请移步原文地址:CENTOS 7更换系统启动默认内核: 环境: CentOS Linux release 7.6.1810 (Core) : 1.查看当前 ...

  10. 如何将本地项目上传到Git 版本库

    1.(先进入项目文件夹)通过命令 git init 把这个目录变成git可以管理的仓库 git init 2.把文件添加到版本库中,使用命令 git add .添加到暂存区里面去,不要忘记后面的小数点 ...