首先介绍下jsonp原理

    浏览器因为同源策略的限制,在不同源的服务器通过我们传统axios是不能直接用来请求数据的(忽略代理),而src标签则不受同源策略的影响,所以我们需要动态的创建带有src的标签让其进行数据的请求,这就是jsonp的原理,在src的URL地址末尾拼接上一个回调函数,用来接受服务器传回来的数据

前端jsonp的封装展示

   //封装一个jsonp请求的函数
function query(opt) {
let str = ""
for (let key in opt) {
str += key + "=" + opt[key] + "&"
}
return str
}
//设置默认回调函数的名字
const defaultOptions = {
callbackName: "callback"
}
function jsonp(url, opt, options = defaultOptions) {
//参数解析 URL为访问的接口 opt为传播的数据 option 为接受参数的回调函数
return new Promise((resolve, reject) => {
//判断下这个?是不是存在
let index = url.indexOf("?");
url += index != -1 ? query(opt) : "?" + query(opt);
url = url + `${options.callbackName}=${options.callbackName}`;
//首先创造一个标签 带有src的
const scriptDom = document.createElement("script");
//设置其src属性
scriptDom.setAttribute("src", url);
//在window系统上创建一个回调函数用来接受数据
window[options.callbackName] = (res) => {
//在接受到了参数动态删除这个script节点和window上面的方法
delete window[options.callbackName];
document.body.removeChild(scriptDom)
//接受成功后调用resolve
if (res) {
resolve(res)
} else {
reject("服务器暂没有获取到数据")
}
}
//动态创建script标记,错误的监听
scriptDom.addEventListener('error', () => {
delete window['jsonpCallback'];
document.body.removeChild(script);
reject('服务器加载失败!');
});
document.body.append(scriptDom)
})
}

调用方式

 <script>
// jsonp("http://localhost:7001/api", {
// user: "zhangsan",
// age: "18"
// }).then(res=>{
// console.log(res);
// }).catch(err=>{
// console.log((err,"失败"))
// }) jsonp(" http://localhost:3000/api", {
user: "zhangsan",
age: "18"
}).then(res => {
console.log(res);
}).catch(err => {
console.log((err, "失败"))
})
</script>

后端我们使用express和egg两款框架分别实现了接口的使用

express的代码展示

 const url = require("url")

 router.get("/api", (req, res, next) => {
//将script标签的src的URL请求转成对象
const opj = url.parse(req.url, true).query;
//然后原理就是调用这个回调函数来进行传参
let {
callback
} = opj;
//如果这个回调函数存在证明是jsonp请求
if (callback) {
let resault = JSON.stringify({
code: 1,
msg: "express框架传回去的参数"
});
res.send(`${callback}(${resault})`)
}
})

egg框架就不需要这么麻烦了 利用中间件可以直接出来

router.js代码
module.exports=app=>{
const {router,controller}=app;
const jsonp = app.jsonp();
router.get("/api",jsonp,controller.index.api) //注意不要写成下面这种
// const {jsonp}=app;
// router.get("/api",jsonp(),controller.index.api)
} controller/index 代码
const {Controller}=require("egg"); class Index extends Controller{
api(ctx){
//直接利用body返回就会传到jsonp的回调函数里面
ctx.body={
code:11,
type:"egg返回的jsonp请求"
}
}
} module.exports=Index;

本文GitHup地址  https://github.com/qiang-chen/cross-domain

网络请求之jsonp封装的更多相关文章

  1. Android项目开发全程(三)-- 项目的前期搭建、网络请求封装是怎样实现的

    在前两篇博文中已经做了铺垫,下面咱们就可以用前面介绍过的内容开始做一个小项目了(项目中会用到Afinal框架,不会用Afinal的童鞋可以先看一下上一篇博文),正所谓麻雀虽小,五脏俱全,这在里我会尽量 ...

  2. iOS 自己封装的网络请求,json解析的类

    基本上所有的APP都会涉及网络这块,不管是用AFNetWorking还是自己写的http请求,整个网络框架的搭建很重要. 楼主封装的网络请求类,包括自己写的http请求和AFNetWorking的请求 ...

  3. 谈谈MVVM和链式网络请求架构

    前言 前一段时间一直在学习iOS的架构.为什么呢? 公司的架构一直是MVC,当我们正式上线的时候,项目已经有了超十万行代码.主要的VC一般都有2000行代码以上. 关键是,目前版本我们只做了三分之一的 ...

  4. Volley网络请求框架的基本用法

    备注: 本笔记是参照了 http://blog.csdn.net/ysh06201418/article/details/46443235  学习之后写下的 简介:  Volley是google官网退 ...

  5. Cocoa Touch(五):网络请求 NSURLSession/AFNetworking, GCD, NSURLResquest

    NSURLRequest 网络请求的关键的就是NSURLRequest类,它的实例表示了请求报文实体以及请求的缓存策略等等,各种网络框架的最终目标都是把这个对象编译成为请求报文发送出去.下面用一个实例 ...

  6. Flutter之网络请求

    Flutter之网络请求 一,介绍与需求 1.1,介绍 1,http一个可组合的,基于Future的库,用于发出HTTP请求.包含一组高级功能和类,可轻松使用HTTP资源.它与平台无关,可以在命令行和 ...

  7. 学习RxJava+Retrofit+OkHttp+MVP的网络请求使用

    公司的大佬用的是这一套,那我这个菜鸟肯定要学习使用了. 我在网上找了很多文章,写的都很详细,比如 https://www.jianshu.com/u/5fd2523645da https://www. ...

  8. 2020,最新APP重构:网络请求框架

    在现在的app,网络请求是一个很重要的部分,app中很多部分都有或多或少的网络请求,所以在一个项目重构时,我会选择网络请求框架作为我重构的起点.在这篇文章中我所提出的架构,并不是所谓的 最好 的网络请 ...

  9. 关于ajax网络请求的封装

    // 封装的ajax网络请求函数// obj 是一个对象function AJAX(obj){ //跨域请求        if (obj.dataType == "jsonp") ...

随机推荐

  1. 斐波那契字符串_KMP

    前言:通过这道题恶补了一下字符串匹配的知识 思路:首先就是求出菲波那切字符串,这个很简单,但是要注意递归超时的问题,可以考虑加上备忘录,或者用递推法,接下来就是匹配问题了,常规的BF会超时,所以要用K ...

  2. H5C3--边框阴影box-shadow

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

  3. 整理Mysql无法创建外键的原因

    在MySQL中创建外键时,经常会遇到问题而失败,这是因为mysql中还有很多细节需要我们去留意,我自己总结并查阅资料后列出了以下几种常见原因. 1.  两个字段的类型或者大小不严格匹配.例如,如果一个 ...

  4. IO流3 --- File类的常用方法2 --- 技术搬运工(尚硅谷)

    File类的判断功能 @Test public void test5(){ File file = new File("hello.txt"); //判断是否是文件目录 Syste ...

  5. 洛谷P2723 丑数 Humble Numbers [2017年 6月计划 数论07]

    P2723 丑数 Humble Numbers 题目背景 对于一给定的素数集合 S = {p1, p2, ..., pK},考虑一个正整数集合,该集合中任一元素的质因数全部属于S.这个正整数集合包括, ...

  6. 开始使用Apache弗林克和Mapr Streams

    Introduction MapR Ecosystem Package 2.0 (MEP) is coming with some new features related to MapR Strea ...

  7. void 运算符

    void 是 javascript 的操作符,意思是:只执行表达式,但没有返回值.该表达式会被计算但是不会在当前文档处装入任何内容,void其实是javascript中的一个函数,接受一个参数,返回值 ...

  8. rescue grub解决方案

    症状: 开机显示:GRUB loading error:unknow filesystem grub rescue> 原因: 已经发现下面几种操作会导致这种问题: 1,想删除ubuntu,于是直 ...

  9. vue制作幻灯片-左右移动

    组件中: <template> <div class="slide-show" @mouseover="clearInv" @mouseout ...

  10. Linux操作系统各版本ISO镜像下载(包括oracle linux\redhat\centos\u

    Linux操作系统各版本ISO镜像下载(包括oracle linux\redhat\centos\ubuntu\debian等) 1.Oracle Linux(下载地址) (1)OracleLinux ...