一、情景需求

调用后台接口需要附带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. [日常] linux设置环境变量

    比如首先在/etc/profile里面增加这几个环境变量 export PATH=$PATH:/mnt/f/ubuntu/goProject/go/binexport GOROOT=/mnt/f/ub ...

  2. sublime相关操作

    装插件 1,安装过Package Control ctrl + shift + p 输入install package 选择 Package Control: Install Package 搜索自己 ...

  3. 《数据挖掘导论》实验课——实验七、数据挖掘之K-means聚类算法

    实验七.数据挖掘之K-means聚类算法 一.实验目的 1. 理解K-means聚类算法的基本原理 2. 学会用python实现K-means算法 二.实验工具 1. Anaconda 2. skle ...

  4. Less(6)

    1.先判断注入类型 (1)首先看到要求,要求传一个ID参数,并且要求是数字型的:?id=1 (2)再输入?id=1' (3)再输入?id=1 and 1=1 (4)再输入?id=1 and 1=2 ( ...

  5. 关于ajax请求不到后台页面提示400 bad request的问题

    解决方法一: 在contrller控制器中对应方法的 @RequestMapping注解中添加 method="RequestMethod.POST"属性

  6. python中list的运算,操作及实例

    在操作list的时候,经常用到对列表的操作运算,比如说,列表添加,删除操作,其实,这里面经常回遇到这样一个问题,就是列表的操作容易被混淆了. 有人做了一个总结,这个很清晰,我就不多做阐述了: 1.ap ...

  7. LeetCode 219: 存在重复元素 II Contains Duplicate II

    题目: ​ 给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的绝对值最大为 k. ​ Given an ...

  8. Springboot异常处理和自定义错误页面

    1.异常来源 要处理程序发生的异常,首先需要知道异常来自哪里? 1.前端错误的的请求路径,会使得程序发生4xx错误,最常见的就是404,Springboot默认当发生这种错误的请求路径,pc端响应的页 ...

  9. IntelliJ中Git突然不能用,报错 xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools)

    记录一个昨天碰到的问题以及解决方法,希望对碰到一样问题的你有用! 昨天升级了一下Mac OS,重启后再打开IntelliJ,突然Git就不能用了,报了下面这样的错: 开始以为是不是Git出了问题,打开 ...

  10. CentOS 7.x 安装 ZSH 终端

    一.安装基本组件 首先执行 yum 命令来安装需要的 zsh 原始程序与 git 程序来 pull 代码. yum install -y zsh git 安装 oh my zsh 脚本 (这一步需要安 ...