js函数只执行一次,函数重写,变量控制与闭包三种做法


风晓
风晓 2024-01-03 00:28:27 55161 赞同 0 反对 0
分类: 资源
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也同样有这个玩法,要不整一篇请求拦截的文章吧。

那么本文到此结束。

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
风晓L1
粉丝 1 资源 2038 + 关注 私信
最近热门资源
桌面通用(全架构)【在双系统环境下隐藏Windows启动菜单】操作指南  2057
银河麒麟桌面操作系统V10(SP1)2203-如何进行远程桌面互访?  1994
银河麒麟桌面操作系统【保留数据盘重装系统】  1804
麒麟系统各种原因开不了机解决(合集)  1587
桌面通用(全架构)【rpm包转成deb包】操作方法  931
银河麒麟桌面操作系统 V10-SP1 双系统安装 efi 分区问题  915
统信系统安装(合集)  853
统信桌面专业版【手动分区安装UOS系统】介绍  845
统启动异常几种类型(initramfs 模式)  688
最近下载排行榜
桌面通用(全架构)【在双系统环境下隐藏Windows启动菜单】操作指南 0
银河麒麟桌面操作系统V10(SP1)2203-如何进行远程桌面互访? 0
银河麒麟桌面操作系统【保留数据盘重装系统】 0
麒麟系统各种原因开不了机解决(合集) 0
桌面通用(全架构)【rpm包转成deb包】操作方法 0
银河麒麟桌面操作系统 V10-SP1 双系统安装 efi 分区问题 0
统信系统安装(合集) 0
统信桌面专业版【手动分区安装UOS系统】介绍 0
统启动异常几种类型(initramfs 模式) 0
作者收入月榜
1

prtyaa 收益393.72元

2

zlj141319 收益220.97元

3

1843880570 收益214.2元

4

IT-feng 收益213.03元

5

风晓 收益208.24元

6

777 收益172.82元

7

Fhawking 收益106.6元

8

信创来了 收益105.89元

9

克里斯蒂亚诺诺 收益91.08元

10

技术-小陈 收益79.5元

请使用微信扫码

加入交流群

请使用微信扫一扫!