一、情景需求

调用后台接口需要附带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();//
fn();//无作为

2.通过变量控制

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

let value = true;
function fn(){
if(value){
//do something
console.log(1);
//执行一次后将变量改为false
value = false;
};
};
fn();//
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); //
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();//
o();//

三、小总结

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

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

那么本文到此结束。

四、参考

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

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

js函数只执行一次,函数重写,变量控制与闭包三种做法的更多相关文章

  1. 小技巧--让JS代码只执行一次

    有时候实在是没办法,就像我这个比赛系统中,有一个弹出框,这个弹出框之外都是模糊的(这是在ajax写出弹出框时,加了一个水印). 然而遇到的问题,也是蹊跷古怪,因为这个弹出框的事件是数据查询事件,但是因 ...

  2. Web下TreeView同一节点连续点击,只执行一次SelectedNodeChanged的解决

    Web下TreeView同一节点连续点击,只执行一次SelectedNodeChanged的解决 http://blog.csdn.net/net_boy/archive/2009/11/05/477 ...

  3. java for循环里面执行sql语句操作,有效结果只有一次,只执行了一次sql mybatis 循环执行update生效一次 实际只执行一次

    java后台controller中,for循环执行数据库操作,但是发现实际仅仅执行了一次,或者说提交成功了一次,并没有实际的个数循环 有可能是同一个对象导致的 可以仔细看一下下面两段代码有什么区别 p ...

  4. selenium+python+unittest:一个类中只执行一次setUpClass和tearDownClass里面的内容(可解决重复打开浏览器和关闭浏览器,或重复登录等问题)

    unittest框架是python自带的,所以直接import unittest即可,定义测试类时,父类是unittest.TestCase. 可实现执行测试前置条件.测试后置条件,对比预期结果和实际 ...

  5. js 中编码(encode)和解码(decode)的三种方法

    js对文字进行编码涉及3个函数:escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decodeURIComponent 下 ...

  6. 2 —— js语法 —— 对象和方法的声明 。变量提升。闭包

    一,声明对象 var obj1 = {}; var obj2 = {name:'kk',age:18,fun:function{          // name,age,fun为对象的属性,只是属性 ...

  7. swift--Timer实现定时器功能,每个一段时间执行具体函数,可以重复,也可以只执行一次

    1,创建 //控制器 timer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(Fifte ...

  8. python内置函数每个执行一次

      open    #   with open('log','r') as f:    或者   r=open(filename,r+) with open ('1.txt','r',encoding ...

  9. JS只执行一次

    1.闭包实现. <script> window.onload = function () { function once(fn) { var result; return function ...

随机推荐

  1. [20191127]表 full Hash Value的计算.txt

    [20191127]表 full Hash Value的计算.txt --//曾经做过表full Hash Value的计算,当时我是通过建立简单的schema以及表名的形式,使用hashcat破解o ...

  2. HTTP 请求夹带(smuggling)攻击

    什么是HTTP请求夹带(smuggling)攻击 HTTP请求走私是一种干扰网站处理从一个或多个用户接收的HTTP请求序列的方式的技术. 请求夹带漏洞危害,允许攻击者绕过安全控制,获取对敏感数据的未授 ...

  3. acwing 853. 有边数限制的最短路 模板

    地址 https://www.acwing.com/problem/content/description/855/ 给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数. 请你求出 ...

  4. 2019-2020-1 20199305《Linux内核原理与分析》第十二周作业

    缓冲区溢出漏洞实验 (一)何为缓冲区溢出漏洞 缓冲区溢出是指程序试图向缓冲区写入超出预分配固定长度数据的情况.这一漏洞可以被恶意用户利用来改变程序的流控制,甚至执行代码的任意片段.这一漏洞的出现是由于 ...

  5. Codechef RIN 「Codechef14DEC」Course Selection 最小割离散变量模型

    问题描述 提供中文版本好评,一直以为 Rin 是题目名字... pdf submit 题解 参考了 东营市胜利第一中学姜志豪 的<网络流的一些建模方法>(2016年信息学奥林匹克中国国家队 ...

  6. Jenkins学习安装配置和使用

    为了能够频繁地将软件的最新版本,及时.持续地交付给测试团队及质量控制团队,以供评审,所以引入持续集成工具Jenkins,从而实现公司新产品持续集成,自动化部署. 环境准备 ●操作系统:Windows1 ...

  7. Linux下dos2unix命令将windows文件编码格式dos转换成Unix格式

    问题描述: 在Windows系统下面使用文本编辑器notepad后传到Linux系统下的话 Linux下处理和执行一般都存在一些问题,我们可以通过命令查看文件是否是dos格式的, 如果有如图所示的M标 ...

  8. Javascript模块化开发3——Grunt之预处理

    一.grunt预处理简述 grunt的注册任务函数本身会对传入的参数和配置对象里的相关属性进行一定的预处理,方便任务函数进行操作. grunt的registerTask方法和registerMulti ...

  9. 工作笔记 之 Linux服务搭建

    No.1 linux环境下安装nginx步骤 Nginx (engine x) 是一款轻量级的Web 服务器.反向代理服务器.电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行. ...

  10. vue template标签

    在普通的html里面: template标签默认有个 display:none; 属性,并且其里面的内容是不可见的. 在vue里面: template标签类似一个隐藏的div,在审查元素的时候是找不到 ...