js 小程序限流函数 return闭包函数执行不了

news/2024/7/20 1:40:51 标签: javascript, 小程序, 前端, 限流

问题:

调用限流 ,没走闭包的函数:  checkBalanceReq()

loadsh.js

// 限流
const throttle = (fn, context, interval) => {
  console.log(">>>>cmm  throttle", context, interval)
  let canRun = true; // 通过闭包保存一个标记
  if (typeof fn != "function") {
    console.log("fn 变量需要是函数")
    return;
  }
  interval = interval ? interval : 500
  console.log(">>开始return", interval)
  return function (e) {//匿名函数
    console.log(">>限流return")
    let args = arguments
    console.log(">>>args", args)
    if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
    canRun = false; // 立即设置为false
    setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
      fn.apply(context, arguments);
      // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
      canRun = true;
    }, 500);
  };
}

module.exports = {
  throttle: throttle,
}

页面调用:点击加减号调用限流方法

const {throttle} = require("../../utils/loadshMy");

Page({
  data: {
    test: "测试",
    OrderCount: 0,
    list: [1, 2, 3, 4, 5, 6, 7, 8, 9]
  },
 
  onChangeNums(e) {
    if (e.target.dataset.add) {
      this.setData({
        OrderCount: this.data.OrderCount + 2
      })
    } else {
      this.setData({
        OrderCount: this.data.OrderCount - 2
      })
    }
    console.log(">>>开始throtthle", this)
    throttle.apply(this, [this.checkBalanceReq, this, 660])
  },

  checkBalanceReq() {
    console.log(">>||----------------执行余额查询")
  }
  onLoad: function (options) {
  }
});

 为什么??

在浏览器HTML ok

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>节流</title>
</head>
<body>
<div>
  <h1>节流:请输入要搜索的内容 <span>0</span></h1>
  <button type="button">点击加1</button>
  <script>
    //节流:在规定时间内, 只触发或者只执行一次对应函数,减少函数的执行。即:频繁触发改为少量触发
    let btn = document.querySelector('button')
    var count = 0
    // btn.onclick = function () {
    //     count++;
    //     document.querySelector('span').innerText = count
    // }


    //    简单实现-settimeout
    function throttle(fn, interval, context) {
      let canRun = true; // 通过闭包保存一个标记
      interval = interval | 500
      return function () {
        console.log(">>interval=" + interval, context)
        if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
        canRun = false; // 立即设置为false
        setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
          fn.apply(this, arguments);
          // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
          canRun = true;
        }, interval);
      };
    }

    function sayHi(e) {
      console.log(e.target.innerWidth, e.target.innerHeight);
      console.log(count + 12)
      pr()
    }

    function pr() {
      console.log(count++)
    }

    window.addEventListener('resize', throttle(sayHi));
    btn.addEventListener('click', throttle(sayHi, 500, this));
  </script>
</div>
</body>
</html>

解决:

发现返回的闭包在使用立即执行,给return的函数用2个括号封装起来()()

因为return的是function,外部访问的时候必须加上括号,不然得到的是function本身的内容,但不执行。如果要得到return后的函数,就是要得到throttle()(),而不是throttle(), 所以return的函数必须加上括号。

最终代码:

loadsh.js

//    简单实现-settimeout
const throttle = (fn, context, interval) => {
  console.log(">>>>|--------15 ------- cmm  throttle", context, fn)
  let canRun = true; // 通过闭包保存一个标记
  if (typeof fn != "function") {
    console.log("fn 变量需要是函数")
    return;
  }
  interval = interval | 500
  console.log(interval)

  return (function () {//匿名函数
    console.log(">>限流return")
    let args = arguments
    console.log(">>>args", args)
    if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
    canRun = false; // 立即设置为false
    setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
      fn.apply(context, arguments);
      // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
      canRun = true;
    }, interval);
  })();
}

module.exports = {
  throttle: throttle
}

问题2:以上代码能执行到回调函数:checkBalanceReq()

但是限流效果没有达到,每次都会执行到回调函数。

分析:wxml页面调用的地方,每次都是一个新的变量,需要做成保存唯一的封包函数。

throttle不要直接用2个括号()(),返回闭包函数

//    简单实现-settimeout
const throttle = (fn, context, interval) => {
  console.log(">>>>|--------15 ------- cmm  throttle", context, fn)
  let canRun = true; // 通过闭包保存一个标记
  if (typeof fn != "function") {
    console.log("fn 变量需要是函数")
    return;
  }
  interval = interval | 500
  console.log(interval)

  return function () {//匿名函数
    console.log(">>限流return")
    let args = arguments
    console.log(">>>args", args)
    if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
    canRun = false; // 立即设置为false
    setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
      fn.apply(context, arguments);
      // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
      canRun = true;
    }, interval);
  };
}

module.exports = {
  throttle: throttle
}

小程序页面对应 js: 页面增加一个变量balanceCallFn,来存储返回的封包函数,不为空的情况直接执行,就不会每次冲掉timer了。

const {throttle} = require('../../utils/loadshMy')
var balanceCallFn
Page({
  data: {
    test: "测试",
    OrderCount: 0,
    list: [1, 2, 3, 4, 5, 6, 7, 8, 9]
  },
  onswitch(e) {
    console.log(e)
    this.setData({
      showinput: true,
      focus: true,
      current: e.target.dataset.index,
    })
  },
  onChangeNums(e) {
    if (e.target.dataset.add) {
      this.setData({
        OrderCount: this.data.OrderCount + 2
      })
    } else {
      this.setData({
        OrderCount: this.data.OrderCount - 2
      })
    }
    console.log(">>>开始throtthle", this)
    if(!balanceCallFn){
              balanceCallFn=throttle.apply(this, [this.checkBalanceReq, this, 660])
       }
       balanceCallFn();
  },
  checkBalanceReq() {
    console.log(">>||----------------执行余额查询")
  },
  bindinputnum(e) {
    console.log(">>>失去点时")
    this.setData({
      showinput: false
    })
  },
  onLoad: function (options) {
  }
});

wxml

<text class="minus" data-minus bindtap="onChangeNums" data-index="{{index}}">-</text>
        <text type="number" class="number" bindtap="onswitch" wx:if="{{!showinput}}">{{OrderCount}}</text>
        <input type="number" class="number" >{{OrderCount}}</input>
        <text class="add"  bindtap="onChangeNums">+</text>

最终,总算执行到回调的方法log OK ,且多次点击也很限流了。 花一个上午时间调试这个问题,还是闭包知识不牢固。


http://www.niftyadmin.cn/n/4947400.html

相关文章

【傅里叶级数与傅里叶变换】数学推导——3、[Part4:傅里叶级数的复数形式] + [Part5:从傅里叶级数推导傅里叶变换] + 总结

文章内容来自DR_CAN关于傅里叶变换的视频&#xff0c;本篇文章提供了一些基础知识点&#xff0c;比如三角函数常用的导数、三角函数换算公式等。 文章全部链接&#xff1a; 基础知识点 Part1&#xff1a;三角函数系的正交性 Part2&#xff1a;T2π的周期函数的傅里叶级数展开 P…

无代码集成飞书连接更多应用

场景描述&#xff1a; 基于飞书开放平台能力&#xff0c;无代码集成飞书连接更多应用&#xff0c;打通数据孤岛。通过Aboter可轻松搭建业务自动化流程&#xff0c;实现多个应用之间的数据连接。 支持包括飞书事件监听和接口调用的能力&#xff1a; 事件监听&#xff1a; 用…

VMWARE15.5.7安装RedHat 7.9黑屏

在win7上面最高版本为vmware15.5.7 我安装后&#xff0c;安装成功了redhat5.5 但是因为操作系统有点老。安装其他软件时遇到问题。想改为7.0以上linux。 但是遇到了问题。安装时&#xff0c;一直黑屏。包括再安装5.5也是同样效果。 找了很多方案都无济于事。后面搜到一个方案…

最优化方法Python计算:基本共轭方向算法

设目标函数 f ( x ) 1 2 x ⊤ H x − x ⊤ b , x ∈ R n . f(\boldsymbol{x})\frac{1}{2}\boldsymbol{x}^\top\boldsymbol{Hx}-\boldsymbol{x}^\top\boldsymbol{b},\boldsymbol{x}\in\text{ℝ}^n. f(x)21​x⊤Hx−x⊤b,x∈Rn. 其中&#xff0c; H ∈ R n n \boldsymbol{H}\i…

Android CCodec (二十) CCodec Native服务实现分析

1、C2解码服务registerAsService注册流程 google实现CCodec的vendor默认解码服务代码路径是在frameworks/av/media/codec2/hidl/services/vendor.cpp中,而其注册的是HIDL服务,本文就对HIDL服务注册做简要分析。首先看下vendor.cpp中的代码注册流程。 int main(int /* argc *…

等保测评--安全计算环境--测评方法

安全子类--身份鉴别 a)应对登录的用户进行身份标识和鉴别,身份标识具有唯一性,身份鉴别信息具有复杂度要求并定期更换; 一、测评对象 终端和服务器等设备中的操作系统(包括宿主机和虚拟机操作系统) 、网络设备(包括虚拟网络设备)、安全设备(包括虚拟安全设备)、移动终端…

pytorch2.0.1 安装部署(cpu+gpu) linux+windows

官网打开可能较慢&#xff0c;耐心等待 pytorch官网 以下操作在默认网络环境即可使用 一、说明和前期准备 1.pytorch是一个和tensorflow类似的框架 如果需要安装tensorflow&#xff0c;可以参考&#xff1a; tensorflow 1&#xff0c;2 cpugpu&#xff08;windowslinux&…

Go 与 Rust

目录 1. Go 与 Rust 1. Go 与 Rust 一位挺 Rust 的网友说道: “我也为这个选择烦恼了很久。最终 Rust 胜出了。首先, 我感觉 Rust 更接近于以前 Pascal 时代的东西, 你可以控制一切; 其次, 如果 wasm 和相关技术大爆发, Rust 将是一个更安全的选择; 然后, 我们已经有了 Python…