JavaScript设计模式(十):牛郎织女-代理模式

本文涉及的产品
.cn 域名,1个 12个月
简介: 牛郎织女-代理模式

代理模式(Proxy)

由于一个对象不能直接引用另一个对象,所以需要通过代理对象在这两个对象之间起到中介的作用。

代理模式解决数据接口请求跨域问题

image.png

$.ajax({
   
   
    url: 'http://www.baidu.com/',
    success: function (res) {
   
   
        // 无法获取返回的数据
    }
});
  • 引发跨域问题的条件:
    1. 同一域名不同的端口号
      • 如: http://www.baidu.com:8001http://www.baidu.com:8002
    2. 同一域名不同协议
      • 如: http://www.baidu.comhttps://www.baidu.com
    3. 域名和域名对应的IP
      • 如: http://www.baidu.comhttp://61.135.169.125
    4. 主域与子域
      • 如: http://www.baidu.comhttp://b.a.com
    5. 子域与子域
      • 如: http://tieba.baidu.comhttp://fanyi.baidu.com

JSONP

当使用 script 标签的时候不会出现跨域问题,可以采用 script 进行解决

imgsrc 也有同样效果,但由于是单向的GET请求,所以在这里并不适用

  • 客户端:
      <body>
          <script>
              /**
               * 请求成功回调
              * @param {string} status   请求状态
              * @param {object} res      请求结果
              */
              function jsonpCallBack(status, res) {
          
          
                  console.log(status, res); // success {name: 'Lee', age: 18}
              }
          </script>
          <script src="http://127.0.0.1:8000?callback=jsonpCallBack&name=Lee"></script>
      </body>
    
  • 服务端:

      const http = require('http');
      const url = require('url');
    
      http.createServer(function (req, res) {
         
         
          let {
         
          query: q } = url.parse(req.url, true);
          let _callback = q['callback'];
          let data = {
         
          name: q['name'], age: 18 };
          res.end(`${_callback}('success', ${JSON.stringify(data)})`);
      }).listen(8000);
    
  • 特点:
    • 这种方式,你可以想象成河里面的一只小船,通过小船将你的请求发送给对岸,然后对岸的人们将数据放在小船里为你带回来

代理模板

利用表单传参,服务端重定向回调实现接收后端返回的数据

image.png

  • http://127.0.0.1:5500/域的文件

    • index.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>牛郎织女-代理模式-代理模板-A页面</title>
        </head>
      
        <body>
            <h1>A页面</h1>
      
            <iframe name="proxyIframe" id="proxyIframe" src=""></iframe>
      
            <form action="http://127.0.0.1:8000/" method="GET" target="proxyIframe">
                <label>回调函数名称:<input type="text" name="callback" value="callback"></label>
                <br />
                <label>重定向地址: <input type="text" name="proxy"
                        value="http://127.0.0.1:5500/demo.html"></label>
                <br />
                <input type="submit" value="提交">
            </form>
      
            <script>
                function callback(data) {
              
              
                    console.log('成功接收到后端返回的数据:', data);
                }
            </script>
        </body>
      
        </html>
      
    • demo.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>牛郎织女-代理模式-代理模板-B页面</title>
        </head>
      
        <body>
            <h1>B页面</h1>
            <script>
                // 获取地址栏传参
                function getUrlParam(url, paramname) {
              
              
                    var reg = new RegExp("(^|&)" + paramname + "=([^&]*)(&|$)");
                    // 查询匹配 substr(1)删除? match()匹配
                    var s = url.substr(1).match(reg);
                    if (s != null) {
              
              
                        return unescape(s[2]); // unescape() 函数可对通过 escape() 编码的字符串进行解码。
                    }
                    return null;
                }
      
                window.onload = function () {
              
              
                    let realURL = decodeURIComponent(location.search);
                    let _callback = getUrlParam(realURL, 'callback');
                    let _data = getUrlParam(realURL, 'data');
                    // 如果不在 index.html(A页面)中,那么不执行
                    if (top == self) return;
                    eval(`top.${_callback}(${_data})`); // 成功接收到后端返回的数据: {name: 'Lee', age: 18}
                };
            </script>
        </body>
      
        </html>
      
  • http://127.0.0.1:8000/域的文件(服务端)

      const http = require('http');
      const url = require('url');
    
      http.createServer(function (req, res) {
         
         
          // 接收参数
          let {
         
          query: {
         
          callback: _callback, proxy: _proxy } } = url.parse(req.url, true);
          // 传参
          let data = {
         
          name: 'Lee', age: 18 };
          // 重定向地址
          let redirectURL = `${_proxy}?callback=${_callback}&data=${
           
           JSON.stringify(data)}`;
          res.statusCode = 302;
          res.setHeader('Location', redirectURL);
          // 结束
          res.end();
      }).listen(8000);
    
相关实践学习
基于函数计算快速搭建Hexo博客系统
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
目录
相关文章
|
1月前
|
设计模式 Java
Java一分钟之-设计模式:装饰器模式与代理模式
【5月更文挑战第17天】本文探讨了装饰器模式和代理模式,两者都是在不改变原有对象基础上添加新功能。装饰器模式用于动态扩展对象功能,但过度使用可能导致类数量过多;代理模式用于控制对象访问,可能引入额外性能开销。文中通过 Java 代码示例展示了两种模式的实现。理解并恰当运用这些模式能提升代码的可扩展性和可维护性。
37 1
|
1月前
|
设计模式 Java 数据库连接
【重温设计模式】代理模式及其Java示例
【重温设计模式】代理模式及其Java示例
|
2天前
|
设计模式 JavaScript 前端开发
[JavaScript设计模式]惰性单例模式
[JavaScript设计模式]惰性单例模式
|
1天前
|
设计模式 安全 Java
Java设计模式:代理模式的静态和动态之分(八)
Java设计模式:代理模式的静态和动态之分(八)
|
1天前
|
设计模式 JavaScript 前端开发
JavaScript设计模式——代理模式
JavaScript设计模式——代理模式
|
2天前
|
设计模式 Java
Java设计模式之代理模式详解
Java设计模式之代理模式详解
|
3天前
|
设计模式
代理模式-大话设计模式
代理模式-大话设计模式
4 0
|
8天前
|
设计模式 编解码 网络安全
结构型设计模式之代理模式
结构型设计模式之代理模式
|
21天前
|
设计模式 架构师 安全
设计模式第五讲-装饰器模式和代理模式详解
远程代理,这种方式通常是为了隐藏目标对象存在于不同地址空间的事实,方便客户端访问。例如,用户申请某些网盘空间时,会在用户的文件系统中建立一个虚拟的硬盘,用户访问虚拟硬盘时实际访问的是网盘空间。
178 0
|
1月前
|
设计模式 JavaScript 前端开发
js设计模式-观察者模式与发布/订阅模式
观察者模式和发布/订阅模式是JavaScript中的两种设计模式,用于处理对象间的通信和事件处理。观察者模式中,一个主题对象状态改变会通知所有观察者。实现包括定义主题和观察者对象,以及在主题中添加、删除和通知观察者的功能。发布/订阅模式则引入事件管理器,允许发布者发布事件,订阅者通过订阅接收通知。