• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

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

武飞扬头像
Lan.W
帮助1

问题:

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

loadsh.js

  1.  
    // 限流
  2.  
    const throttle = (fn, context, interval) => {
  3.  
    console.log(">>>>cmm throttle", context, interval)
  4.  
    let canRun = true; // 通过闭包保存一个标记
  5.  
    if (typeof fn != "function") {
  6.  
    console.log("fn 变量需要是函数")
  7.  
    return;
  8.  
    }
  9.  
    interval = interval ? interval : 500
  10.  
    console.log(">>开始return", interval)
  11.  
    return function (e) {//匿名函数
  12.  
    console.log(">>限流return")
  13.  
    let args = arguments
  14.  
    console.log(">>>args", args)
  15.  
    if (!canRun) return; // 在函数开头判断标记是否为true,不为truereturn
  16.  
    canRun = false; // 立即设置为false
  17.  
    setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
  18.  
    fn.apply(context, arguments);
  19.  
    // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return
  20.  
    canRun = true;
  21.  
    }, 500);
  22.  
    };
  23.  
    }
  24.  
     
  25.  
    module.exports = {
  26.  
    throttle: throttle,
  27.  
    }
学新通

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

学新通

  1.  
    const {throttle} = require("../../utils/loadshMy");
  2.  
     
  3.  
    Page({
  4.  
    data: {
  5.  
    test: "测试",
  6.  
    OrderCount: 0,
  7.  
    list: [1, 2, 3, 4, 5, 6, 7, 8, 9]
  8.  
    },
  9.  
     
  10.  
    onChangeNums(e) {
  11.  
    if (e.target.dataset.add) {
  12.  
    this.setData({
  13.  
    OrderCount: this.data.OrderCount 2
  14.  
    })
  15.  
    } else {
  16.  
    this.setData({
  17.  
    OrderCount: this.data.OrderCount - 2
  18.  
    })
  19.  
    }
  20.  
    console.log(">>>开始throtthle", this)
  21.  
    throttle.apply(this, [this.checkBalanceReq, this, 660])
  22.  
    },
  23.  
     
  24.  
    checkBalanceReq() {
  25.  
    console.log(">>||----------------执行余额查询")
  26.  
    }
  27.  
    onLoad: function (options) {
  28.  
    }
  29.  
    });
学新通

 为什么??

在浏览器HTML ok

  1.  
    <!DOCTYPE html>
  2.  
    <html lang="en">
  3.  
    <head>
  4.  
    <meta charset="UTF-8">
  5.  
    <title>节流</title>
  6.  
    </head>
  7.  
    <body>
  8.  
    <div>
  9.  
    <h1>节流:请输入要搜索的内容 <span>0</span></h1>
  10.  
    <button type="button">点击加1</button>
  11.  
    <script>
  12.  
    //节流:在规定时间内, 只触发或者只执行一次对应函数,减少函数的执行。即:频繁触发改为少量触发
  13.  
    let btn = document.querySelector('button')
  14.  
    var count = 0
  15.  
    // btn.onclick = function () {
  16.  
    // count ;
  17.  
    // document.querySelector('span').innerText = count
  18.  
    // }
  19.  
     
  20.  
     
  21.  
    // 简单实现-settimeout
  22.  
    function throttle(fn, interval, context) {
  23.  
    let canRun = true; // 通过闭包保存一个标记
  24.  
    interval = interval | 500
  25.  
    return function () {
  26.  
    console.log(">>interval=" interval, context)
  27.  
    if (!canRun) return; // 在函数开头判断标记是否为true,不为truereturn
  28.  
    canRun = false; // 立即设置为false
  29.  
    setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
  30.  
    fn.apply(this, arguments);
  31.  
    // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return
  32.  
    canRun = true;
  33.  
    }, interval);
  34.  
    };
  35.  
    }
  36.  
     
  37.  
    function sayHi(e) {
  38.  
    console.log(e.target.innerWidth, e.target.innerHeight);
  39.  
    console.log(count 12)
  40.  
    pr()
  41.  
    }
  42.  
     
  43.  
    function pr() {
  44.  
    console.log(count )
  45.  
    }
  46.  
     
  47.  
    window.addEventListener('resize', throttle(sayHi));
  48.  
    btn.addEventListener('click', throttle(sayHi, 500, this));
  49.  
    </script>
  50.  
    </div>
  51.  
    </body>
  52.  
    </html>
学新通

解决:

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

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

最终代码:

loadsh.js

  1.  
    // 简单实现-settimeout
  2.  
    const throttle = (fn, context, interval) => {
  3.  
    console.log(">>>>|--------15 ------- cmm throttle", context, fn)
  4.  
    let canRun = true; // 通过闭包保存一个标记
  5.  
    if (typeof fn != "function") {
  6.  
    console.log("fn 变量需要是函数")
  7.  
    return;
  8.  
    }
  9.  
    interval = interval | 500
  10.  
    console.log(interval)
  11.  
     
  12.  
    return (function () {//匿名函数
  13.  
    console.log(">>限流return")
  14.  
    let args = arguments
  15.  
    console.log(">>>args", args)
  16.  
    if (!canRun) return; // 在函数开头判断标记是否为true,不为truereturn
  17.  
    canRun = false; // 立即设置为false
  18.  
    setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
  19.  
    fn.apply(context, arguments);
  20.  
    // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return
  21.  
    canRun = true;
  22.  
    }, interval);
  23.  
    })();
  24.  
    }
  25.  
     
  26.  
    module.exports = {
  27.  
    throttle: throttle
  28.  
    }
学新通

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

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

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

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

  1.  
    // 简单实现-settimeout
  2.  
    const throttle = (fn, context, interval) => {
  3.  
    console.log(">>>>|--------15 ------- cmm throttle", context, fn)
  4.  
    let canRun = true; // 通过闭包保存一个标记
  5.  
    if (typeof fn != "function") {
  6.  
    console.log("fn 变量需要是函数")
  7.  
    return;
  8.  
    }
  9.  
    interval = interval | 500
  10.  
    console.log(interval)
  11.  
     
  12.  
    return function () {//匿名函数
  13.  
    console.log(">>限流return")
  14.  
    let args = arguments
  15.  
    console.log(">>>args", args)
  16.  
    if (!canRun) return; // 在函数开头判断标记是否为true,不为truereturn
  17.  
    canRun = false; // 立即设置为false
  18.  
    setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
  19.  
    fn.apply(context, arguments);
  20.  
    // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return
  21.  
    canRun = true;
  22.  
    }, interval);
  23.  
    };
  24.  
    }
  25.  
     
  26.  
    module.exports = {
  27.  
    throttle: throttle
  28.  
    }
学新通

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

  1.  
    const {throttle} = require('../../utils/loadshMy')
  2.  
    var balanceCallFn
  3.  
    Page({
  4.  
    data: {
  5.  
    test: "测试",
  6.  
    OrderCount: 0,
  7.  
    list: [1, 2, 3, 4, 5, 6, 7, 8, 9]
  8.  
    },
  9.  
    onswitch(e) {
  10.  
    console.log(e)
  11.  
    this.setData({
  12.  
    showinput: true,
  13.  
    focus: true,
  14.  
    current: e.target.dataset.index,
  15.  
    })
  16.  
    },
  17.  
    onChangeNums(e) {
  18.  
    if (e.target.dataset.add) {
  19.  
    this.setData({
  20.  
    OrderCount: this.data.OrderCount 2
  21.  
    })
  22.  
    } else {
  23.  
    this.setData({
  24.  
    OrderCount: this.data.OrderCount - 2
  25.  
    })
  26.  
    }
  27.  
    console.log(">>>开始throtthle", this)
  28.  
    if(!balanceCallFn){
  29.  
    balanceCallFn=throttle.apply(this, [this.checkBalanceReq, this, 660])
  30.  
    }
  31.  
    balanceCallFn();
  32.  
    },
  33.  
    checkBalanceReq() {
  34.  
    console.log(">>||----------------执行余额查询")
  35.  
    },
  36.  
    bindinputnum(e) {
  37.  
    console.log(">>>失去点时")
  38.  
    this.setData({
  39.  
    showinput: false
  40.  
    })
  41.  
    },
  42.  
    onLoad: function (options) {
  43.  
    }
  44.  
    });
学新通

wxml

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

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

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhiahhbc
系列文章
更多 icon
同类精品
更多 icon
继续加载