The return closure function of the current limiting function of the js applet cannot be executed

question:

Call the current-limiting function without closure:   checkBalanceReq()

Business logic:

1. Current limiting function: loadshMy.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; 
    canRun = false; // 立即设置为false
    setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
      fn.apply(context, arguments);
      canRun = true;
    }, 500);
  };
}

module.exports = {
  throttle: throttle,
}

2. Page call: Click the plus and minus signs to call the current limiting method,

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

 The result of the operation is: the checkBalanceReq() method cannot be adjusted. Why? ?

3. Test: run the same logic in the browser HTML, it is OK to run the callback, WHY?

<!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
 
    function throttle(fn, interval, context) {
      let canRun = true; 
      interval = interval | 500
      return function () {
        console.log(">>interval=" + interval, context)
        if (!canRun) return;
        canRun = false;
        setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
          fn.apply(this, arguments);
          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>

solve:

It is found that the returned closure is executed immediately, and the return function is encapsulated with 2 parentheses () ()

Because the return is a function, you must add parentheses when accessing externally, otherwise you will get the content of the function itself, but it will not be executed. If you want to get the function after return, you need to get throttle()() instead of throttle(), so the return function must be added with parentheses.

The code of the callback function will be executed immediately:

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
}

New question 2:

The above business code can be executed to the callback function: checkBalanceReq() , but the current limiting effect is not achieved. Every time the button is clicked, the callback function will be executed.

problem analysis:

The place where the wxml page is called is a new variable every time, and it needs to be made to save the only package function.

Throttle do not directly use two brackets ()(), the return closure function is stored in a global variable of the current page.

 The final complete OK code:

//    简单实现-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
}

The applet page corresponds to the js: page to add a variable balanceCallFn to store the returned packet function, and execute it directly if it is not empty, so that the timer will not be flushed every time.

(throttle.apply() makes the internal this of the call point to the current page this)

.js 

const {throttle} = require('../../utils/loadshMy')
var balanceCallFn
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)
    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>-</text>
 <input type="number" class="number" >{
   
   {OrderCount}}</input>
  <text class="add" data-add bindtap="onChangeNums">+</text>

In the end, the callback method log OK is finally executed, and multiple clicks are also very limited. Spend a morning debugging this problem, or closure knowledge is not strong.

Guess you like

Origin blog.csdn.net/LlanyW/article/details/132337919