什么是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. 05-4-style的代替操作

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. Compile_Netgen_WITH_OpenCascade

    title: Compile_Netgen_WITH_OpenCascade date: 2016-04-23 21:14:42 tags: 结合OCCT编译Netgen date: 2016-04- ...

  3. Python3读取深度学习CIFAR-10数据集出现的若干问题解决

    今天在看网上的视频学习深度学习的时候,用到了CIFAR-10数据集.当我兴高采烈的运行代码时,却发现了一些错误: # -*- coding: utf-8 -*- import pickle as p ...

  4. Leetcode513. Find Bottom Left Tree Value找树左下角的值

    给定一个二叉树,在树的最后一行找到最左边的值. 示例 1: 输入: 2 / \ 1 3 输出: 1 示例 2: 输入: 1 / \ 2 3 / / \ 4 5 6 / 7 输出: 7 注意: 您可以假 ...

  5. Vue基础知识梳理

    1. Vue 实例 1.1 创建一个Vue实例 一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实例,以及可选的嵌套的.可复用的组件树组成.demo 1.2 数据与方法 数据的响应式渲 ...

  6. leetcode 49 Group Anagram

    lc49 Group Anagram 逻辑很简单,就是统计字母出现次数,然后将完全相同的字符串放入同一list 关键是怎么实现 统计的部分,可以通过将string排序,Arrays.sort(),或者 ...

  7. mysql查看执行计划重构后的查询

    MYSQL优化器会对客服端发送的SQL语句进行优化,优化后的SQL语句再被MYSQL执行.然后我们在优化SQL的时候,怎么获取到MYSQL优化后执行语句呢. EXPLAIN select * from ...

  8. fastjson循环引用 问题@ManyToOne @OneToOne返回数据中"$ref"问题

    返回数据为 这样前端就无法获取正确数据(至少是不改变代码,不增加代码量的情况下) 所以还是改返回值比较好 根据查阅 https://blog.csdn.net/qq_38487524/article/ ...

  9. Python_异常处理try...except、raise

    一.try...except 有时候我们写程序的时候,会出现一些错误或异常,导致程序终止.例如,做除法时,除数为0,会引起一个ZeroDivisionError 例子: 1 2 3 4 a=10 b= ...

  10. spring源码学习之bean的加载(二)

    这是接着上篇继续写bean的加载过程,好像是有点太多了,因为bean的加载过程是很复杂的,要处理的情况有很多,继续... 7.创建bean 常规的bean的创建时通过doCreateBean方法来实现 ...