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();//
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也同样有这个玩法,要不整一篇请求拦截的文章吧。
那么本文到此结束。
四、参考
Javascript写一个once函数,让传入函数只执行一次
js函数只执行一次,函数重写,变量控制与闭包三种做法的更多相关文章
- 小技巧--让JS代码只执行一次
有时候实在是没办法,就像我这个比赛系统中,有一个弹出框,这个弹出框之外都是模糊的(这是在ajax写出弹出框时,加了一个水印). 然而遇到的问题,也是蹊跷古怪,因为这个弹出框的事件是数据查询事件,但是因 ...
- Web下TreeView同一节点连续点击,只执行一次SelectedNodeChanged的解决
Web下TreeView同一节点连续点击,只执行一次SelectedNodeChanged的解决 http://blog.csdn.net/net_boy/archive/2009/11/05/477 ...
- java for循环里面执行sql语句操作,有效结果只有一次,只执行了一次sql mybatis 循环执行update生效一次 实际只执行一次
java后台controller中,for循环执行数据库操作,但是发现实际仅仅执行了一次,或者说提交成功了一次,并没有实际的个数循环 有可能是同一个对象导致的 可以仔细看一下下面两段代码有什么区别 p ...
- selenium+python+unittest:一个类中只执行一次setUpClass和tearDownClass里面的内容(可解决重复打开浏览器和关闭浏览器,或重复登录等问题)
unittest框架是python自带的,所以直接import unittest即可,定义测试类时,父类是unittest.TestCase. 可实现执行测试前置条件.测试后置条件,对比预期结果和实际 ...
- js 中编码(encode)和解码(decode)的三种方法
js对文字进行编码涉及3个函数:escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decodeURIComponent 下 ...
- 2 —— js语法 —— 对象和方法的声明 。变量提升。闭包
一,声明对象 var obj1 = {}; var obj2 = {name:'kk',age:18,fun:function{ // name,age,fun为对象的属性,只是属性 ...
- swift--Timer实现定时器功能,每个一段时间执行具体函数,可以重复,也可以只执行一次
1,创建 //控制器 timer = Timer.scheduledTimer(timeInterval: 0.001, target: self, selector: #selector(Fifte ...
- python内置函数每个执行一次
open # with open('log','r') as f: 或者 r=open(filename,r+) with open ('1.txt','r',encoding ...
- JS只执行一次
1.闭包实现. <script> window.onload = function () { function once(fn) { var result; return function ...
随机推荐
- Redis集群模式下的redis-py-cluster方式读写测试
与MySQL主从复制,从节点可以分担部分读压力不一样,甚至可以增加slave或者slave的slave来分担读压力,Redis集群中的从节点,默认是不分担读请求的,从节点只作为主节点的备份,仅负责故障 ...
- TCP服务端
出处: https://blog.csdn.net/DGH2430284817/article/details/86653294问题描述: 在用socket的通信中,经常会出现这种情况,客 ...
- PHP 生成 UUID 函数
Generate name based md5 UUID (version 3) /** * Generate name based md5 UUID (version 3). * @example ...
- IT兄弟连 HTML5教程 多媒体应用 小结及习题
小结 在互联网上,图像和链接则是通过URL唯一确定信息资源的位置.URL分为绝对URL和相对URL.通过使用<img />标记在浏览器中显示一张图像.超文本具有的链接能力,可层层链接相关文 ...
- Unix 开发中的 Make 三连
Unix 开发过程中,经常性的操作是从源码编译安装相应库文件,所以下面三个命令便是家常便饭,俗称三连: ./configure make make install 下面来看看这三步分别做了什么. co ...
- ASP.NET MVC教程五:ASP.NET MVC中的路由
一.概述 在ASP.NET MVC架构中,控制器在3大核心构件中处于中心地位,通过控制器支配模型和视图,然而从浏览器发出的请求到控制器还需要路由的协助,路由将特定的请求和控制器的动作对应起来. 在AS ...
- 基于asp.net(C#)MVC+前端bootstrap+ztree+lodash+jquery技术-Angel工作室通用权限管理
一.Angel工作室简单通用权限系统简介 AngelRM(Asp.net MVC Web api)是基于asp.net(C#)MVC+前端bootstrap+ztree+lodash+jquery技术 ...
- PHP实现支付宝登录
1.支付宝路由拼接 public function dev() { $http = 'https://openauth.alipaydev.com/oauth2/publicAppAuthorize. ...
- 订单结算submit_order.php扣库存,扣账号金额(学生笔记)
<?php header("Content-type: text/html; charset=utf-8"); session_start(); include_once(& ...
- Easyui 去除jquery-easui tab页div自带滚动条
去除jquery-easui tab页div自带滚动条 by:授客 QQ:1033553122 测试环境 jquery-easyui-1.5.3 需求场景 打开tab页面时,自动载入一个iframe页 ...