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

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

  例如在某个动作的时候需要触发三个异步方法,他们为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. phpcms 替换首页

    利用phpcms制作企业站,首先要将静态的企业主页替换成后台可编辑的动态主页. 首先做一个静态的企业站主页: <!DOCTYPE html> <html> <head&g ...

  2. SpringMvc拦截器小测试

    前言 俗话说做项目是让人成长最快的方案,最近小编写项目的时候遇到了一个小问题.小编在项目中所负责的后台系统,但是后台系统是通过系统的页面是通过ifame联动的,那么这时候问题就来了,后台所做的所有操作 ...

  3. BZOJ 2142: 礼物

    模非素数下的排列组合,简直凶残 调着调着就过了= = 都不知道怎么过的= = 直接上链接http://hi.baidu.com/aekdycoin/blog/item/147620832b567eb4 ...

  4. linux c++ 加载动态库常用的三种方法

    链接库时的搜索路径顺序:LD_LIBRARY_PATH --> /etc/ld.so.conf --> /lib,/usr/lib 方法1. vi .bash_profile    设置环 ...

  5. Loadrunner之脚本编写

    先打开loadrunner的服务器(打开成功之后会出现一个绿色的X) 以订票系统为例(http://127.0.0.1:1080/WebTours/) 录制一个登陆的脚本. 利用C语言编写一个简单的脚 ...

  6. Springboot 整合 Dubbo/ZooKeeper 详解 SOA 案例

    摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢!   “看看星空,会觉得自己很渺小,可能我们在宇宙中从来就是一个偶然.所以,无论什么事情,仔细想一 ...

  7. 【Unity优化】我所理解的IL指令

    版权声明:本文为博主原创文章,欢迎转载.请保留博主链接:http://blog.csdn.net/andrewfan 指令格式 英文单词全写 指令解释 nop no operation perform ...

  8. 警惕一大波银行类木马正在靠近,新型BankBot木马解析

    背景 来自安全公司Dr.Web的研究人员说,最近一个未命名的Android银行木马源代码在地下黑客论坛遭到了泄露.就在近期,阿里聚安全检测到大量新型BankBot家族木马,木马伪装成Good Weat ...

  9. 数据库基础——(SQLserver)约束

                                                              数据库定义:一些存储在硬盘上的数据文件 内存:计算机临时存储的一些数据 .net - ...

  10. Android学习总结(十五) ———— Notification(状态栏通知)基本用法

    一.Notification基本概念  Notification是一种具有全局效果的通知,它展示在屏幕的顶端,首先会表现为一个图标的形式,当用户向下滑动的时候,展示出通知具体的内容.我们在用手机的时候 ...