首页 > 其他分享 >JSONP前端流程

JSONP前端流程

时间:2023-07-31 22:11:33浏览次数:32  
标签:script text 前端 JSONP id let jsonp data 流程

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`);
})

进阶参考

标签:script,text,前端,JSONP,id,let,jsonp,data,流程
From: https://www.cnblogs.com/fangchaoduan/p/17594742.html

相关文章

  • 微商城小程序怎么开发?(微商城小程序开发流程)
    微商城小程序作为一个便捷的电商平台,成为越来越多企业和个人的选择。它不仅为商家提供了一个在线销售的渠道,也为消费者提供了更方便快捷的购物体验。那么,如何开发一个成功的微商城小程序呢?接下来广州名锐讯动将介绍微商城小程序的开发流程,并分享一些关键步骤和注意事项。第一步:需求......
  • web前端学习第一天
    一、web应用程序开发介绍    1.界面部份    2.业务逻辑部份    3.数据存储部份 二、 web应用程序开发三大核心技术   HTML CSS  JAVASCRIPT    html:超文本标记语言        作用:网页内容、结构    css:......
  • UI/UE统一设计与前端组件库建设
    一、当前问题(主要在管理后台)1、输入框、下拉选择框figma样式不一致2、search组件、table组件、翻页导航样式与交互不一致3、UI/UE设计成本高4、前端开发成本高二、原因分析1、设计师需要拥有全局视角,各平台统一规划。通常来说当一个界面设计美观、交互体验感好、并......
  • sam之自动生成mask代码流程
    本文不涉及sam的训练流程,只设计推理过程最近接触这个sam,由于网络中关于sam的自动mask功能的介绍较少,所以本周对源码进行了解读说到sam自动提取mask,包含三个部分,第一个部分是如何对原始图像进行分割成一个个小块,第二部分是送到sam中进行处理得出结果,第三个是如何对一个个小块的结......
  • 未来几年,前端框架的竞争格局会发生什么变化?
    过去几年,前端框架领域的竞争是激烈的。各个框架在功能、性能、开发体验、生态系统和社区支持等方面都有不同的优势和特点。开发者和企业需要根据具体项目需求、团队技能和偏好来选择最适合的框架。前端技术一直在快速演进,新的标准、语言和工具不断涌现,这也为竞争增添了新的维度......
  • 开发环境搭建_前端环境搭建
       一定要在没有中文的目录下启动 ......
  • SpringMvc的执行流程及工作原理
     先上图针对流程图解析一下:用户发送请求至前端控制器DispatcherServlet前端控制器DispatcherServlet收到请求调用处理器映射器HandlerMapping。处理器映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给Dispa......
  • 未来前端框架将持续推进组件化开发
    未来前端框架的发展将持续聚焦在组件化开发、性能优化和打包体积、跨平台开发、小程序框架的崛起、深度集成TypeScript、用户体验和可访问性、全球化和国际化等方向。通过不断地创新和改进,前端框架将推动Web应用开发的进步,为用户提供更好的使用体验和开发者更高效的开发体验。开......
  • vue2集成bpmn流程图,可导入导出预览等
    1.使用到的组件组件源码版本licensebpmn-js地址7.3.1bpmn.iobpmn-js-properties-panel地址0.37.2MITcamunda-bpmn-moddle地址4.5.0MIT版本一定要对,否则可能会报错2.组件代码<template><divid="app"><divclass="container">......
  • 验证码识别全流程实战
    本文将介绍验证码的历史与发展、验证码破解的历史与发展,验证码破解全流程实战。验证码的历史与发展验证码,全称为“CompletelyAutomatedPublicTuringtesttotellComputersandHumansApart”,即全自动区分计算机和人类的图灵测试,Captcha。早在上个世纪90年代,为了防止恶......