javascript设计模式-代理模式

代理模式是为一个对象提供一个代用品或占位符,以便控制对他的访问。

代理模式是一种非常有意义的模式,在生活中可以找到很多代理的场景。比如,明星都有经纪人作为代理,明星不会主动与主办方谈论价格和演出的细节,往往是由他的经纪人出面,把商业细节谈好之后,再把合同交由给明星签名。

而我通常使用到代理模式,往往是会在操作一些开销比较大的运算结果提供暂时的存储,在下次运算的时候,如果传递进来的参数与之前一致,则直接返回前面存储的运算结果。

我在日常维护工作中,曾经遇到一个场景。在一个后台管理系统中,表格承担着非常重要的角色,而在原有的模块中,是一个分页的表格,每次点击分页的按钮都会向服务器发起数据请求,但其实在一定的程度上会造成资源的浪费。因为,我们更加希望,如果用户已经点击分页按钮的"1",“2”,“3”…的时候,下次再点击则不会向服务器发起请求。

为了让读者们能更好理解代理模式,下面有几个简单的例子:

缓存代理—计算乘积
创建一个用于求乘积的函数

     let mult = function () {
      let a = 1;
      for (let i = 0; i < arguments.length; i++) {
        a = a * arguments[i];
      }
      return a;
    }

加入缓存的代理函数

let createCacheFun = function (fn) {
      let cache = {};
      return function () {
        console.log(fn);
        let arg = Array.prototype.join.call(arguments, ",");
        if (arg in cache) {
          return cache[arg];
        }
        return cache[arg] = fn.apply(this, arguments);
      }
    }
    let a = createCacheFun(mult);
    console.log(a(1, 2, 3, 4)); // 首次计算的结果
    console.log(a(1, 2, 3, 4)); // 缓存后的计算结果

当我们第二次调用createCacheFun (1,2,3,4)的时候,mult 函数并没有被计算,而是直接返回之前缓存好的计算结果,通过增加缓存代理的方式,mult函数可以继续专注于自身的职责–计算乘积,缓存的功能是由代理对象实现的。

那么我们又回到刚刚的场景,利用缓存代理用于ajax异步请求数据。为了方便起见,使用的技术栈前台为bootstrap+jquery,后台为node+mysql。
在这里插入图片描述

把jquery中的Ajax转换成Promise的形式。

let baseUrl = "http://localhost:8002"; // 请求地址
    let baseParams = { // 默认展示参数
      currentPage: 1,
      pageSize: 5
    }
    let cache = {} // 缓存的对象

    function Ajax(url, params) {
      params = Object.assign(baseParams, params); // 合并传递过来的参数
      if (!cache[params.currentPage]) {
        cache[params.currentPage] = {}
      }
      return new Promise((resolve, reject) => {
        if (Object.keys(cache[params.currentPage]).length > 0) { // 判断缓存对象时候存在值
          return resolve(cache[params.currentPage])
        } else {
          $.ajax({
            url: baseUrl + url,
            type: "GET",
            data: Object.assign(baseParams, params),
            success: function (data) {
              cache[params.currentPage] = data; // 记录已经请求后的数据
              resolve(data);
            },
            error: function (data) {
              reject(data);
            }
          })
        }

      })
    }

初次加载和创建节点的方法

// 开始加载
    Ajax("/bookList", baseParams).then(res => {
      let data = res.message
      createdTr(data);
    })
    // 创建节点的方法
    let createdTr = (function () {
      return function (data) {
        $(".table tbody").html("")
        let str = "";
        $.each(data, (i) => {
          str += `
        <tr>
            <td>${data[i].bookName}</td>
            <td>${data[i].bookPrice}</td>
            <td>${data[i].author}</td>
          </tr>
        `
        })
        $(".table tbody").append(str);
      }
    })()

点击分页按钮,数据发生切换。

// 列表点击
    $(".pagination li").click(function () {
      let num = $(this).find("a").text();
      if (isNaN(num)) {
        return;
      }
      $(this).addClass("active").siblings("li").removeClass("active");
      Ajax("/bookList", {
        currentPage: parseInt(num)
      }).then(res => {
        let data = res.message
        createdTr(data);
      })
    })

在这里插入图片描述

利用高阶函数动态创建代理

通过传入高阶函数这种更加灵活的方式,把ajax方法作为一个参数传入一个专门用于创建缓存代理的工厂函数。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.0/css/bootstrap.css" rel="stylesheet">
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
</head>

<body>
  <div class="container">
    <div class="panel panel-default">
      <div class="panel-body">
        <table class="table table-striped table-bordered text-center">
          <tr>
            <td>书名</td>
            <td>价格</td>
            <td>作者</td>
          </tr>

        </table>
      </div>
      <div class="panel-footer">
        <nav aria-label="Page navigation">
          <ul class="pagination">
            <li>
              <a href="#" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
              </a>
            </li>
            <li class="active"><a href="#">1</a></li>
            <li><a href="#">2</a></li>
            <li><a href="#">3</a></li>
            <li><a href="#">4</a></li>
            <li><a href="#">5</a></li>
            <li>
              <a href="#" aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
              </a>
            </li>
          </ul>
        </nav>
      </div>
    </div>
  </div>
  <script>
    let baseUrl = "http://localhost:8002";
    let baseParams = {
      currentPage: 1,
      pageSize: 5
    }

    function Ajax(url, params) {
      params = Object.assign(baseParams, params);
      return new Promise((resolve, reject) => {
        $.ajax({
          url: baseUrl + url,
          type: "GET",
          data: Object.assign(baseParams, params),
          success: function (data) {
            resolve(data);
          },
          error: function (data) {
            reject(data);
          }
        })
      })
    }
    // 创建节点的方法
    let createdTr = (function () {
      return function (data) {
        $(".table tbody").html("")
        let str = "";
        $.each(data, (i) => {
          str += `
        <tr>
            <td>${data[i].bookName}</td>
            <td>${data[i].bookPrice}</td>
            <td>${data[i].author}</td>
          </tr>
        `
        })
        $(".table tbody").append(str);
      }
    })()
    //  高阶函数实现缓存代理
    let createCacheFun = function (fn) {
      let cache = {};
      return function (url, baseParams) {
        // console.log(baseParams);
        if (!cache[baseParams.currentPage]) {
          cache[baseParams.currentPage] = fn.apply(this, arguments);
        }
        return cache[baseParams.currentPage];
      }
    }
    // 开始加载
    let cacheAjax = createCacheFun(Ajax);
    cacheAjax("/bookList", baseParams).then((res) => {
      console.log(res);
      let data = res.message
      createdTr(data);
    })
    // 列表点击
    $(".pagination li").click(function () {
      let num = $(this).find("a").text();
      if (isNaN(num)) {
        return;
      }
      $(this).addClass("active").siblings("li").removeClass("active");
      cacheAjax("/bookList", {
        currentPage: parseInt(num)
      }).then(res => {
        let data = res.message
        createdTr(data);
      })
    })
  </script>
</body>

</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip基于Django+python编写开发的毕业生就业管理系统支持学生教师角色+db数据库(毕业设计新项目).zip
毕设新项目基于python3.7+django+sqlite开发的学生就业管理系统源码+使用说明(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 学生就业管理系统(前端) ## 项目开发环境 - IDE: vscode - node版本: v12.14.1 - npm版本: 6.13.4 - vue版本: @vue/cli 4.1.2 - 操作系统: UOS 20 ## 1.进入项目目录安装依赖 ``` npm install ``` ## 2.命令行执行进入UI界面进行项目管理 ``` vue ui ``` ## 3.编译发布包(请注意编译后存储路径) #### PS:需要将编译后的包复制到后端项目的根目录下并命名为'static' 学生就业管理系统(后端) ## 1.项目开发环境 - IDE: vscode - Django版本: 3.0.3 - Python版本: python3.7.3 - 数据库 : sqlite3(测试专用) - 操作系统 : UOS 20 ## 2.csdn下载本项目并生成/安装依赖 ``` pip freeze > requirements.txt pip install -r requirements.txt ``` ## 3.项目MySQL数据库链接错误 [点击查看解决方法](https://www.cnblogs.com/izbw/p/11279237.html)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值