什么是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. 5行代码怎么实现Hadoop的WordCount?

    初学编程的人,都知道hello world的含义,当你第一次从控制台里打印出了hello world,就意味着,你已经开始步入了编程的大千世界,这和第一个吃螃蟹的人的意义有点类似,虽然这样比喻并不恰当 ...

  2. 【NOIP2013模拟联考7】OSU

    [NOIP2013模拟联考7]OSU 描述 Description osu 是一款群众喜闻乐见的休闲软件. 我们可以把osu的规则简化与改编成以下的样子: 一共有n次操作,每次操作只有成功与失败之分, ...

  3. js的简单介绍和相关的必备常识

    一.概念 1.js是JavaScript的缩写,是运行在浏览器端或服务端的依附于页面的脚本语言. 2.js的学习分为:ECMA语法.Dom网页对象模型.Bom浏览器的对象模型 3.ECMA是浏览器厂商 ...

  4. 错误 2 error C2059: 语法错误:“::”

    设置项目属性,在预定义处理器中添加定义NOMINMAX来禁止使用Vsual C++的min/max宏定义. 项目属性   ——> C/C++ ——> 预处理器 ——> 预处理器定义 ...

  5. 19-10-18-Night-U

    话说T3: 一句话题意……见过这个嘛…… 于是:$\sum \limits_{i!=j} \binom{a_i+b_i+a_j+b_j}{a_i+a_j}$ ------------前言结束----- ...

  6. substring() 方法用于提取字符串中介于两个指定下标之间的字符。

    substring() 方法用于提取字符串中介于两个指定下标之间的字符. 语法 stringObject.substring(start,stop) 参数 描述 start 必需.一个非负的整数,规定 ...

  7. 转:linux select 多路复用机制

    源地址:http://blog.csdn.net/turkeyzhou/article/details/8609360 2013-02-25 14:18 442人阅读 评论(1) 收藏 举报   目录 ...

  8. spring-jdbc-aop事务

    1 spring整合JDBC 1.1 概述 spring提供了很多模板整合Dao技术  spring中提供了一个可以操作数据库的对象.对象封装了jdbc技术. JDBCTemplate => J ...

  9. oracle基础学习(1)

    -解锁用户,需要使用dba权限conn sys/1234 as dba; alert user scott account unlock;/ --initcap方法,实现字符串首字符大写,其余字符小写 ...

  10. 移植别人的vcpkg包到自己的项目

    修改该目录下的文件即可: 或者修改你的项目文件下的所有不对的路径,类似于这种: