JSONP前端流程

JSONP总体思路

  1. 后端先给前端一个接口文档。

    • https://www.baidu.com/sugrec?prod=pc&wd=用户输入的文字&cb=后端要调用的前端定义的全局函数名
  2. 前端会封装一个jsonp函数:它的作用是传入特定参数,返回一个Promise实例。
    1. 会用jsonp的方式来请求后端数据,把后端数据通过Promise实例返回。

      • 此时这个Promise实例的状态为"pending"。
    2. 它内部会创建一个临时的唯一方法名jQuery_202301010101。并自动生成一个全局函数,该函数的功能就是把传入的入参resolve()出去。

      window[`jQuery_202301010101`] = function (data) {
      resolve(data); //把data传递给了resolve函数,也就是传递给了成功的回调函数,所以jsonp后面的then就会执行了。
      }
    3. 并把这个临时的唯一方法名通过构建一个script标签通过get发送请求传递给后端。

      • 之后后端会返回一段动态的js代码,如临时的唯一方法名(前端想要的数据)jQuery_202301010101({name:'6666',list:[{id:1,text:'文字1'},{id:2,text:'文字2'}]})

      • 浏览器会把后端返回的jQuery_202301010101({name:'6666',list:[{id:1,text:'文字1'},{id:2,text:'文字2'}]})当成js代码在全局作用域中执行。

        jQuery_202301010101({name:'6666',list:[{id:1,text:'文字1'},{id:2,text:'文字2'}]})
        //相当于:window[`jQuery_202301010101`]({name:'6666',list:[{id:1,text:'文字1'},{id:2,text:'文字2'}]})
        window[`jQuery_202301010101`] = function (data) {
        resolve(data); //把data传递给了resolve函数,也就是传递给了成功的回调函数,所以jsonp后面的then就会执行了。
        }
      • 此时这个Promise实例的状态为"fulfilled",值就为后端要返回的json数据,如{name:'6666',list:[{id:1,text:'文字1'},{id:2,text:'文字2'}]}

  3. 用户触发事件,会调用jsonp函数,得到一个Promise实例。此时代码就执行到了jsonp函数中。
    1. 一开始这个Promise实例的状态为"pending",在后端返回一段动态的js代码并在浏览器中执行后,该Promise实例的状态就变成"fulfilled",同时then()中得到的结果值就是后端返回的json数据。
    2. Promise实例的状态变成"fulfilled"后,通过then()拿到后端返回的json数据,如{name:'6666',list:[{id:1,text:'文字1'},{id:2,text:'文字2'}]},并重新渲染页面。

代码说明

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<input id="search-word" />
<ul id="suggestions"></ul>
<script>
function jsonp(options) {
return new Promise((resolve, reject) => {
const { url, jsonp, data } = options;
let callbackName = `jQuery_${Date.now()}`; //1.或者创建一个临时的、唯一的方法名。
//给window添加一个全局变量,变量名为方法名,值是一个只会给后端调用一次的函数。
window[callbackName] = function (data) {
delete window[callbackName];
document.body.removeChild(script);
resolve(data); //把data传递给了resolve函数,也就是传递给了成功的回调函数,所以jsonp后面的then就会执行了。
};
//动态创建一个类型为script的对象或者说元素
let script = document.createElement("script");
let queryStr = url.indexOf("?") === -1 ? "?" : "&";
for (let key in data) {
queryStr += `${key}=${data[key]}&`;
}
script.src = `${url}${queryStr}${jsonp}=${callbackName}`; //得到一个url地址。
script.onerror = (error) => reject(error);
document.body.appendChild(script); //向body的尾部添加一个script对象,之后浏览器就会向服务器发起一个get请求。请求回来的其实是字符串,但浏览器会把那些字符串当成js代码来执行。//后端返回的数据格式为:前端传递给的函数名(前端想要的数据对象) 如:jQuery_998888({name:'前端想要的数据',...}) //浏览器在拿到这个后端返回的数据后,就相当于在全局作用域下运行了一遍后端的代码。
});
}
let searchWord = document.getElementById("search-word");
let suggestions = document.getElementById("suggestions");
const handleInput = (event) => {
let wd = event.target.value;
const thePromise = jsonp({
url: "https://www.baidu.com/sugrec", //也可能为https://www.baidu.com/sugrec?prod=pc
jsonp: "cb", //百度的后端规定了这个字段就叫cb。但网易的可能的约定为callback或者cbf之类的,反正是后端规定的。
data: { prod: "pc", wd }, //其它要传递给服务器的数据,它们都会拼接到查询字符串中。这个有些字段是前端定的,有些字段是后端定的。
}); thePromise
.then((result) => {
//这个就是后端返回的 jQuery_998888({name:'前端想要的数据',...}) 中的 {name:'前端想要的数据',...}。
let { g } = result;
if (g) {
0;
let html = "";
for (let i = 0; i < g.length; i++) {
html += `<li>${g[i].q}</li>`;
}
suggestions.innerHTML = html;
}
})
.catch((error) => {
console.log(error);
});
};
searchWord.addEventListener("input", handleInput);
</script>
</body>
</html>

前后端交互模板

  • fang/f20230731/1.basic/doc/jsonp.html 这个就是前端写的代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>jsonp</title>
</head>
<body>
动态jsonp。这里是自动生成的`Live Server`起起来的;
<script>
let callbackName = `JQuery_${Date.now()}`;
console.log(`动态函数变量名:callbackName-->`, callbackName); window[callbackName] = async (data) => {
console.log(`后端返回的json数据:data-->`, data);
await new Promise((resolve, reject) => {
setTimeout(() => {
resolve(data666);
}, 300000);
}); // 执行结束后,移除多余代码。
console.log(`执行结束后,移除多余代码。`);
window[callbackName] = null;
document.body.removeChild(script);
}; let script = document.createElement("script");
script.src = `http://localhost:8111/sugrec.js?cb=${callbackName}`;
console.log(`动态生成的脚本标签:script-->`, script); document.body.appendChild(script);
</script>
</body>
</html>
  • fang/f20230731/1.basic/doc/jsonp.js 这个是后端服务器的代码。
// 这里是用node起起来的,服务器端口为8111;
const http = require('http')
const url = require('url')
http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/javascript')
const { query: { cb } } = url.parse(req.url || '', true)//这里是为了让后端拿到前端定义的那个函数的函数名。
console.log(`cb-->`, cb);//这里是在命令行中打印的。 const jsonObj = { 'id': 100, name: '这个是后端构建出来的json数据' }//这个就是后端要返回的json数据。
//let script = `${cb}(${jsonStr})`//实际上大多数的jsonp交互中,后端返回的代码就是这个格式。
const jsonStr = JSON.stringify(jsonObj)
let script = `
// 这里是服务器那边动态生成的js代码。
console.log('开始执行服务器返回的动态js代码。')
${cb}(${jsonStr});
console.log('结束执行服务器返回的动态js代码。')
`
res.end(script);
}).listen(8111, () => {
console.log(`服务器地址为: http://localhost:8111`);
})

进阶参考

JSONP前端流程的更多相关文章

  1. 亚信UED前端流程自动化构建工具

    亚信UED前端流程自动化构建工具 .wmd-input, .wmd-input:focus, #md-section-helper {font-size: 14px !important;line-h ...

  2. 微信小程序支付功能前端流程

    只是分享一下小程序支付功能的前端流程和代码, 仅供参考(使用的是uni app). handleCreate () { /** 第一步:前台将商品数据发送到后台,后台创建订单入库并返回订单id等信息 ...

  3. 新手学习WEB前端流程以及学习中常见的误区

    学习web前端编程技术肯定是以就业拿到高薪工作为主要目的的,可是高薪不会那么轻易拿到,这是一个最简单的道理.没有付出就没有回报,在整个学习web前端编程技术的过程中,你需要付出时间.精力.金钱.废话不 ...

  4. 如何正确学习web前端流程以及如何找工作

    解释一下web前端工作是做啥的,Web前端开发工程师,主要职责是利用(X)HTML/CSS/JavaScript/Flash等各种Web技术进行客户端产品的开发.完成客户端程序(也就是浏览器端)的开发 ...

  5. Django 项目补充知识(JSONP,前端瀑布流布局,组合搜索,多级评论)

    一.JSONP 1浏览器同源策略 通过Ajax,如果在当前域名去访问其他域名时,浏览器会出现同源策略,从而阻止请求的返回 由于浏览器存在同源策略机制,同源策略阻止从一个源加载的文档或脚本获取或设置另一 ...

  6. 从0搭建Vue3组件库(六):前端流程化控制工具gulp的使用

    前言 随着前端诸如webpack,rollup,vite的发展,gulp感觉似乎好像被取代了.其实并没有,只不过它从台前退居到了幕后.我们仍然可以在很多项目中看到它的身影,比如elementplus. ...

  7. Gulp常用前端流程自动化配置

    前言 近期的项目全部由Grunt + LESS 转向改用Gulp + SASS 进行前端开发,也就奔着Gulp那比较好用的自定义函数而来的. 一.package.json文件配置如下: { " ...

  8. GruntJS常用前端流程自动化配置-【持续优化】

    前言 近期用Grunt进行前端开发经常要用到的一些Grunt插件,用起来非常顺手. 一.package.json文件配置如下: 包括coffeescript编译为js,css加CSS3适配前缀,css ...

  9. svn迁移gitlab,构建前端打包发布流程

    前端资源迁移     目前公司的前端资源托管在svn服务器上,由于团队的逐渐扩大,svn的分支管控越来越不灵活,而且对于以后前端流程一体化的处理支持不是很好,因此决定在版本控制上转向git.git的好 ...

  10. 前端工程化开发之yeoman、bower、grunt

    上两遍文章介绍了前端模块化开发(以seaJs为例)和前端自动化开发(以grunt为例)的流程,参见: http://www.cnblogs.com/luozhihao/p/4818782.html ( ...

随机推荐

  1. [Pytorch框架] 4.2.1 使用Visdom在 PyTorch 中进行可视化

    文章目录 4.2.1 使用Visdom在 PyTorch 中进行可视化 安装 坑 基本概念 Environments Panes VIEW 可视化接口 使用 绘制简单的图形 更新损失函数 import ...

  2. 【Azure Developer】Azure AD 注册应用的 OAuth 2.0 v2 终结点获取的 Token 解析出来依旧为v1.0, 这是什么情况!

    问题描述 使用 Azure AD 注册应用 Oauth2 v2.0的终结点(OAuth 2.0 token endpoint (v2):https://login.partner.microsofto ...

  3. Pwn系列之Protostar靶场 Stack6题解

    源码如下: #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <stri ...

  4. #Python 缺失值的检测与处理,检测部分

    Python  缺失值的检测与处理,分两部分笔记,第一部分是检测缺失值部分

  5. 2020-10-29:使用redis实现分布式限流组件,要求高并发场景同一IP一分钟内只能访问100次,超过限制返回异常,写出实现思路或伪代码均可。

    福哥答案2020-10-29: 简单回答:固定窗口:string.key存ip,value存次数.滑动窗口:list.key存ip,value=list,存每次访问的时间. 中级回答:固定窗口:用re ...

  6. 分类树,我从2s优化到0.1s

    前言 Java技术突击网站:http://www.susan.net.cn 分类树查询功能,在各个业务系统中可以说随处可见,特别是在电商系统中. 但就是这样一个简单的分类树查询功能,我们却优化了5次. ...

  7. 代码随想录算法训练营Day9|字符串KMP算法总结

    代码随想录算法训练营 代码随想录算法训练营Day9字符串|KMP算法 8. 实现 strStr() 459.重复的子字符串 字符串总结 双指针回顾 28. 实现 strStr() KMP算法 题目链接 ...

  8. .NET 创建无边框的跨平台应用

    .NET 创建无边框的跨平台应用 在创建了Photino应用程序以后我们发现它自带了一个标题栏,并且非常丑,我们现在要做的就是去掉这个很丑的自带标题栏,并且自定义一个更好看的,下面我们将用Masa B ...

  9. Mysql DDL执行方式-pt-osc介绍 | 京东云技术团队

    1 引言 大家好,接着上次和大家一起学习了<MySQL DDL执行方式-Online DDL介绍>,那么今天接着和大家一起学习另一种MySQL DDL执行方式之pt-soc. 在MySQL ...

  10. 万字长文讲透 RocketMQ 4.X 消费逻辑

    RocketMQ 是笔者非常喜欢的消息队列,4.9.X 版本是目前使用最广泛的版本,但它的消费逻辑相对较重,很多同学学习起来没有头绪. 这篇文章,笔者梳理了 RocketMQ 的消费逻辑,希望对大家有 ...