有没有这么一个场景,你的一个动作需要在所有异步方法执行完毕后,再进行操作?然而你对异步方法何时执行完毕感到困扰,只能在每个方法中写回调,在回调中重复劳动?

  偶然的,想起了之前经理讲过的闭包的概念,偶然的,觉得可以应用到代码中。

  例如在某个动作的时候需要触发三个异步方法,他们为a(),b(),c()。我们在d()方法中执行a,b,c。然后在三个方法执行后需要抛出一个动作,然而我们怎么知道这三个异步方法什么时候执行完呢?并且准确的在执行完的最后那个方法后抛出这个动作呢?

  //异步a
function a(cb){
.....
     if(cb)cb();
}
//异步b
function b(cb){
.....
     if(cb)cb();
}
//异步c
function c(cb){
.....
    if(cb)cb();
}
//动作
function action(){
...
}
//调用者
function main(){
a();
b();
c();
action();
}

  原本我是用一个全局变量count记录执行次数,在每个方法的回调中将执行次数减去。当有一个回调方法内的count被减为0的时候,就证明方法都执行完毕了。

    var count=3;
//异步a
function a(){
.....
if(--count<=0){
action();
}
}
//异步b
function b(){
.....
if(--count<=0){
action();
}
}
//异步c
function c(){
.....
if(--count<=0){
action();
}
}
//调用者
function main(){
a();
b();
c();
//action();
}

  是的,这个方法是能实现的,但是这个方法有点弊端,首先count是个固定值,你必须事先知道有多少个方法要执行,就是要自己数,如果新加了方法,那还要重新改变count的值,很明显这和我们的'开放-关闭'原则是背道而驰的。其次每个方法都要写一串相同的代码,复用性太低,重复性代码太多。最后,每个方法都要访问全局变量,这增加了全局资源,用我们经理说过的话,就是因为方法内的逻辑污染了到外部或全局代码。

  明白了这样写的弊端,自然是要改了。  

  《代码大全》中对'表查询法'有着很高的评价,即简洁了代码,又增加了可读性,在一些场景中甚至是提高代码性能的利器,我们何不利用?

initFun:function(){    //初始化
var funArr = [a, b, c];
funArr.forEach(function (item) {
item();
})
}

  好了,接下来如何用闭包实现准确在三个方法执行后调用回调?

  在这之前,我们先看看闭包的特性:访问外部变量,保持外部变量。

  访问外部变量就是能在方法内访问外部变量,参数,局部变量或函数。保持外部变量是指把访问的外部变量拘留在这个方法的上下文中,每次调用方法都会带着这个上下文。简单来说就是把我们访问的这个外部变量存储在了这个方法的内存中,类似自带一个全局变量一样。

  那么我们该如何应用到代码中呢?

    //异步a
function a(cb){
.....
    if(cb)cb();
}
//异步b
function b(cb){
.....
    if(cb)cb();
}
//异步c
function c(){
.....
     if(cb)cb();
}
  ......
//闭包调用
function closureFun(closureCount, closureCb) {var count = closureCount;
var callback = closureCb;
return function () {
if (!--count) {
callback();
}
}
},
//初始化
function initFun(){
     var funArr = [a, b, c];
//执行完所有异步方法后的回调方法
var callBack = function () { console.log('i am callback'); }
//注册闭包代码
var testClosureFun = me.methods.closureFun(funArr.length, callBack);
funArr.forEach(function (item) {
item(testClosureFun);
})
},

  初始化方法中参照表查询法,将方法暂留在一个数组中,写好回调方法,并将其注册到闭包方法。funArr.length是这个闭包方法访问的外部变量,是闭包内部判断后最终将运行的次数,每次运行完一个方法,数量减一,当所有方法执行完毕,count也就为0了,这时候就会调用回调方法。

  这段代码没有污染到全局,方法的数量也自动计算,每个方法中抽离了重复代码,也算是优化了点吧。

  虽然这不一定是最好的选择,但能在偶然间把自己学到的知识应用到实际中,成就感自然也是满满的。

  当然这优化手段有什么缺陷或不足,望能指出,如果有更好的重构方案,有人知道并能指点一二,那也是鄙人的荣幸了。

javascript的闭包与一次重构的感受的更多相关文章

  1. 深入理解JavaScript的闭包特性如何给循环中的对象添加事件

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  2. JavaScript作用域闭包简述

    JavaScript作用域闭包简述 作用域 技术一般水平有限,有什么错的地方,望大家指正. 作用域就是变量起作用的范围.作用域包括全局作用域,函数作用域以块级作用域,ES6中的let和const可以形 ...

  3. JavaScript的闭包原理

    什么是js(JavaScript)的闭包原理,有什么作用? 一.定义 官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 个人的理解是 ...

  4. Js(javaScript)的闭包原理

    问题?什么是js(javaScript)的闭包原理,有什么作用? 一.定义 官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.  小编 ...

  5. 深入理解javascript的闭包

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...

  6. 如何给循环中的对象添加事件--深入理解JavaScript的闭包特性

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  7. javascript,jquery(闭包概念)(转)

    偶尔听人说javascript闭包,让我联想起以前学编译原理和数字逻辑里讲的闭包,以前上课讲的闭包很难懂,而且含有递归的意思在里面,现在不想再查看里面的闭包概念. 但javascript我是经常要用, ...

  8. 理解Javascript 的闭包(closure)

    要理解闭包的概念先从变量的作用域说去 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之 ...

  9. 两个示例介绍JavaScript的闭包

    JavaScript的闭包有两个用途:一个是访问函数内部的变量:另一个是让变量的值在作用域内保持不变.函数是JavaScript 中唯一有作用域的对象,因此JavaScript的闭包依赖于函数实现,下 ...

随机推荐

  1. 微信公众号开发总结(Node.js + express + winston)

    关于订阅号.服务号.企业号 官方定位 订阅号:主要偏于为用户传达资讯(类似报纸杂志),认证后每天可以群发一条消息,可达到宣传效果,构建与读者之间更好的沟通和管理模式. 服务号:主要偏于服务交互(类似银 ...

  2. linux编译内核

    ubuntu 14.04 编译内核出现unable to locate package ncurses-devel 问题的解决   首先,在make menuconfig的时候就会提示没有 nucrs ...

  3. 如何通过注解Bean类来封装SQL插入语句

    整体思路是酱紫的: 给bean上注解说明该bean对应着数据库中哪张表,给每个bean的属性都注解说明各自对应着这张表的哪个字段. 通过类反射获取表名,通过逐个反射每个属性的getter方法,获取注解 ...

  4. 4105: [Thu Summer Camp 2015]平方运算

    首先嘛这道题目只要知道一个东西就很容易了:所有循环的最小公约数<=60,成一条链的长度最大为11,那么我们就可以用一个很裸的方法.对于在链上的数,我们修改直接暴力找出并修改.对于在环上的数,我们 ...

  5. BZOJ 3432: [Usaco2014 Jan]Cross Country Skiing (二分+染色法)

    还是搜索~~可以看出随着D值的增大能到达的点越多,就2分d值+染色法遍历就行啦~~~ CODE: #include<cstdio>#include<iostream>#incl ...

  6. 康复计划#4 快速构造支配树的Lengauer-Tarjan算法

    本篇口胡写给我自己这样的老是证错东西的口胡选手 以及那些想学支配树,又不想啃论文原文的人- 大概会讲的东西是求支配树时需要用到的一些性质,以及构造支配树的算法实现- 最后讲一下把只有路径压缩的并查集卡 ...

  7. muduo库整体架构简析

    muduo是一个高质量的Reactor网络库,采用one loop per thread + thread loop架构实现,代码简洁,逻辑清晰,是学习网络编程的很好的典范. muduo的代码分为两部 ...

  8. iOS回顾笔记( 01 )

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  9. JavaScript的for循环中嵌套一个点击事件为何点击一次弹出多个相同的值

    先看下面一段代码: for(var i=0; i<10; i++) { $('#ul').bind('click', function() { alert(i) }) } 对于这段代码,当点击I ...

  10. 第36篇 Asp.Net源码解析(一)

    上面两篇文章说了http协议和IIS处理,这次说下当IIS把请求交给Asp.net后的过程. AppManagerAppDomainFactory 当IIS把请求交给asp.net时候,如果AppDo ...