zoukankan      html  css  js  c++  java
  • js函数只执行一次,函数重写,变量控制与闭包三种做法

    一、情景需求

    调用后台接口需要附带token信息,那么在每个请求的头部添加token的做法就不太优雅了;一个网站请求100次,那就得写添加100次token,假设某天接口有所变动,改起来就十分麻烦了。

    公司项目开发使用的框架是angularjs,正好angularjs有一个请求拦截的功能;意思就是,每次请求的发起,请求拦截都能感知,所以添加token的事我们就可以在请求拦截统一处理。

    为了保证请求拦截添加token永远是有效的,我在这里除了添加token,也增加了现有token的过期判断,如果token不存在,或者存在已过期,都得重新拿一次token。

    结果骚操作就来,一个页面有10个请求,第一个请求触发token判断并发现已过期,就去请求新的token,巧的是请求token的接口也出了问题,并未能拿回最新token;于是第二个请求也触发了请求拦截,发现token用不了,也去请求新token,同样失败了。

    第三次请求拦截失败.....第四次,第五次......第十次,如果这个页面请求更多呢,永无止境了。于是,后台接口成功被我玩炸了。

    那么问题来了,请求拦截次数是根据请求触发的,如果token用不了,我去拿新token的操作不管成功失败,其实都只用触发一次,成功了一次搞定,失败了请求100次也都是多余。那么引出我们的问题,如果让js函数只执行一次:

    二、实现

    1.函数重写

    我在js模式第五篇博客有提过函数重写,在这里就是十分适用了:

    function fn() {
        //do something...
        console.log(1);
        //函数重写
        fn = function () {};
    };
    fn();//1
    fn();//无作为

    2.通过变量控制

    原理很简单,声明一个默认为true的变量,在执行一次后修改为false,通过条件判断是否需要执行:

    let value = true;
    function fn(){
        if(value){
            //do something
            console.log(1);
            //执行一次后将变量改为false
            value = false;
        };
    };
    fn();//1
    fn();//无作为

    3.利用闭包

    我们可以利用闭包封装一个通用函数,将你需要只执行一次的函数作为参数传入闭包,也可以达到类似的效果:

    //封装执行一次通用函数
    function once(fn) {
        if (Object.prototype.toString.call(fn) !== "[object Function]") {
            throw new Error('请传递一个函数');
        };
    
        return function (...rest) {
            if (fn) {
                fn.apply(this, rest);
                fn = null;
            };
        };
    };
    
    //我们希望只执行一次的函数
    function fn(a, b) {
        console.log(a + b);
    };
    
    //调用闭包函数
    let onlyOnce = once(fn);
    
    onlyOnce(1, 2); //3
    onlyOnce(); //无作为

    我在网上看到了另外一种写法,原理类似,适用于一次执行的函数有返回值的情况,在第一次调用后,不管再调用几次都将跳过执行过程,直接返回第一次执行的值,也非常实用:

    function once(fn) {
        let can, result;
    
        if (Object.prototype.toString.call(fn) !== "[object Function]") {
            throw new Error('请传递一个函数');
        };
    
        return function (...rest) {
            if (can) {
                return result;
            };
    
            can = true;
            result = fn.apply(this, rest);
            //释放fn保存的函数,便于被垃圾回收
            fn = null;
            return result;
        };
    };
    
    function fn() {
        return 1;
    };
    
    let o = once(fn);
    o();//1
    o();//1

    三、小总结

     我们在了解很多知识的时候,总会纳闷这个东西的使用场景在哪里,那么阅读完本文,你大概了解了如果让js中函数只执行一次的三种做法,同时也结合了我的需求,对这种用法在何时使用有了一个了解。

    我在文章开头提到了angularjs的请求拦截,我发现,vue也同样有这个玩法,要不整一篇请求拦截的文章吧。

    那么本文到此结束。

    四、参考

    让js中的函数只有一次有效调用的三种常用方法

    Javascript写一个once函数,让传入函数只执行一次

  • 相关阅读:
    解决AJAX中使用UpdatePanel后再用无法弹出对话框问题
    <转>JavaScript 参考教程资料之文档对象
    C#中图片的重绘
    csv数据源的创建(二)
    开始试用windows live writer
    与BW相关各模块常用tcode及Table
    SAP中的client(也叫集团)的意义
    SAP中的client(也叫集团)的意义(中文版)
    BW报表igs服务配置解决中文显示问题
    开源.net论坛有那些?
  • 原文地址:https://www.cnblogs.com/echolun/p/11123905.html
Copyright © 2011-2022 走看看