前言

在日常开发中,也许我们会遇到这样的一个问题。我们利用【发布订阅模式】(如果不了解的可以直接访问此链接www.cnblogs.com/xiaoxiaokun… )去执行【发布】事件时,遇到函数内部涉及到异步执行时,就比较难以处理。为了满足这种需求,我专门写了一个这样的插件用于函数整合队列并顺序执行。

函数队列循环执行

/**
*1.0.0.1版本
*/
var list=[];//存储函数
list.push(function(){
console.log(1);
});
list.push(function(){
console.log(2);
});
list.push(function(){
console.log(3);
});
for (var i=0;fn=list[i++];) {
fn();//执行
}

结果:1,2,3
这是最简单的方式,可以实现函数整合成一个队列,按照先进先出顺序执行。现在在仔细看发现,如果函数中有异步执行那函数执行就不能保证按照顺序执行,例如:

var list=[];//存储函数
list.push(function(){
console.log(1);
});
list.push(function(){
setTimeout(function() {
console.log(2);
}, 2000);
});
list.push(function(){
console.log(3);
});
for (var i=0;fn=list[i++];) {
fn();//执行
}

输出的结果肯定是 1,3,2

/**
*1.0.0.2版本
*/
var list=[];
list.push(function(){
console.log(1);
});
list.push(function(){
console.log(2);
});
list.push(function(){
console.log(3);
}); function start(list){
if(list.length){
list.shift()();
arguments.callee(list);
}
}
start(list);

这种方式可以等到执行完毕,清除list内部执行过后的函数。不影响下次push 执行。但是异步函数还是未解决。

/**
*1.0.0.3版本
*/
var list=[];//存储数组的集合
list.push(function(){
console.log(1);
});
list.push(function(callback){
//callback是代表这个函数是异步的函数
setTimeout(function() {
console.log(2);
callback();//执行完异步函数执行回调函数
}, 2000);
});
list.push(function(){
console.log(3);
}); function start(){
//判断数组的长度
if(list.length){
var fn=list.shift();//取出数组第一个函数
//判断函数是否带有参数
if(fn.length){
fn(start);//执行该函数,并且把 start本身传递进去。
}else{
fn();
start();
}
}
}
start();

此版本可以解决带有异步执行的函数按照刚开始push进去的顺序依次执行。
需要注意的是,如果函数是内部带有异步执行的函数,需要传递一个参数来告诉start。但是如果我们push进去的函数本身有好多个参数这需要怎么办呢!!接下来看另一版本。

/**
*1.0.0.4版本
*/
var list=[];//存储数组的集合
list.push(function(){
console.log(1);
});
list.push(function(callback){
setTimeout(function() {
console.log(2);
callback();
}, 2000);
});
list.push(function(){
console.log(3);
}); function start(){
//判断数组的长度
if(list.length){
var fn=list.shift();//取出数组第一个函数
//判断函数是否带有参数
if(fn.length && getfunarg(fn)[0]=='callback'){
fn(start);//执行该函数,并且把 start本身传递进去。
}else{
fn();
start();
}
}
}
start();
/**
* 查找函数参数名
* @fn {Function } 要查找的函数
* @return []返回参数数组
* */
function getfunarg(fn) {
var f = /^[\s\(]*function[^(]*\(\s*([^)]*?)\s*\)/.exec(fn.toString());
return f && f[1] ? f[1].split(/,\s*/) : [];
}

到现在为止,我们这几个函数基本已经满足我们的需求,但是push的时候,假设函数多个参数,我们还需进一步优化代码!为了把这个插件做的更好。我决定还是把callback放在最后,这样就能保证函数传递参数不受影响。

最终版本

/**
* 作者:小小坤
* 联系:java-script@qq.com
* 日期:2017-11-11
* 版本:1.0.0.4
* -----------使用说明----------
* 1、把所有函数【包含异步执行的函数】按照顺序依次 使用lk.push存入
* 2、带有参数的函数,一定要注意{最一个参数如果是callback}会被认为是 异步执行函数
* 3、异步执行的函数,需要把最一个参数设置为callback。并在函数执行完毕执行callback();函数保证按照顺序执行
*
* */
;! function() {
var list = [], //存储函数的列表
isFun = Object.prototype.toString; //用于验证是否是函数
/**
* 添加到列表中
* @fn {Function} 函数体
* */
function push(fn) {
isFun.call(fn) === "[object Function]" && list.push(fn);
};
/**
* 开始执行列表中的所有函数,
* 按照先进先出原则
*
* */
function star() {
if(list.length) {
var fn = list.shift(),//截取第一个函数
arry=getfunarg(fn),//获取这个函数的参数列表
_length=arry.length;//参数列表的长度
if(_length && arry[_length-1] === 'callback') {
if(_length===1){
fn(star);
}else{
arry.pop();//删除最后一个参数
arry.push(star);//把回调函数存入数组
fn.apply(this,arry);
}
} else {
fn.apply(this,arry);
star();
}
}
}
/**
* 查找函数参数名
* @fn {Function } 要查找的函数
* @return []返回参数数组
* */
function getfunarg(fn) {
var f = /^[\s\(]*function[^(]*\(\s*([^)]*?)\s*\)/.exec(fn.toString());
return f && f[1] ? f[1].split(/,\s*/) : [];
}
//挂在到Windows上。
window.lk = {
push: push,
start: star
}
}();
//使用测试
/**--------一条华丽的分割线--------**/
var a=100,
b=200,
d=300,
f=400; //定义函数 a2 ,此函数带有一个参数,被认为是异步函数
function a2(a,b,callback) {
console.time('2');
setTimeout(function() {
console.timeEnd('2');
callback();
console.log(a,'a');
}, 1000);
}
//把函数函数 a2 放入数组
lk.push(a2); //定义函数 a3
function a3(d, f) {
console.log(f,'f');
console.log(3);
}
//把函数函数 a3 放入数组
lk.push(a3); //定义函数 a4 此函数带有一个参数,被认为是异步函数
function a4(callback) {
console.time('4');
setTimeout(function() {
console.timeEnd('4');
callback();
}, 2000);
}
//把函数函数 a4 放入数组
lk.push(a4); //最后开始执行
lk.start();

最终此插件完成,需要压缩的同学可以自行压缩。代码比较简单,提供了两个方法。
push存储函数列表
start开始执行

总结

通过上边的代码编写我们学到了处理函数列表时候,需要考虑到异步函数。处理异步函数,需要回调函数参与。这样就能帮助代码按照顺序执行。

js函数整合队列顺序执行插件的更多相关文章

  1. js函数和变量的执行顺序【易错】

    js函数和变量的声明与执行顺序 一.函数执行顺序 1.正常顺序 function f(){ alert(2); } f(); //alert 2 所有浏览器都能测试通过. 2.倒序调用 f(); // ...

  2. 【原创】cs+html+js+css模式(七): 顺序执行与并发执行问题,IIS7及其以上版本的抛错问题解决

          在进行开发的过程中,针对于这种模式,我们继承的IRequiresSessionState,这种对于我们的同一个IIS的执行中是顺序执行即一个ajax请求处理完成后,才能执行下一个ajax, ...

  3. js函数的解析与执行过程

    function f(a,b,c){ alert(a);//函数字符串 alert(b); var b = 5; function a(){ } } f(1,2); //预处理 lexicalEnvi ...

  4. 在JS函数中执行C#中的函数、字段

    1.调用字段 cs文件的代码: ; protected void Page_Load(object sender, EventArgs e) { id = ; } js页面的代码: function ...

  5. 各种常用js函数实现

    1.bind function bind(fn, context) {    var args = Array.prototype.slice.call(arguments, 2);    retur ...

  6. 如何编写高质量的 JS 函数(1) -- 敲山震虎篇

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/7lCK9cHmunvYlbm7Xi7JxQ作者:杨昆 一千个读者,有一千个哈姆雷特. 此系列文 ...

  7. jquery和js的几种页面加载函数的方法以及执行顺序

    参考博客:http://www.cnblogs.com/itslives-com/p/4646790.html    https://www.cnblogs.com/james641/p/783837 ...

  8. js函数和变量的声明与执行顺序

    一.函数执行顺序 1.正常顺序 function f(){ alert(2); } f(); //alert 2 所有浏览器都能测试通过. 2.倒序调用 f(); //alert 2 function ...

  9. js的并行加载以及顺序执行

    重新温习了下这段内容,发现各个浏览器的兼容性真的是搞大了头,处理起来很是麻烦. 现在现总结下并行加载多个js的方法: 1,对于动态createElement('script')的方式,对所有浏览器都是 ...

随机推荐

  1. Zabbix(二) : Zabbix Server端配置文件说明

    Zabbix Server端配置文件说明 # This is a configuration file for Zabbix Server process # To get more informat ...

  2. PHP的ntohl网络字节序函数及相关知识

    PHP与C服务器的socket通信,在做数据转换的时候,PHP没有提供对应将网络字节序和机器字节序相互转换的程序,但是根据函数的意义,我们可以做相应的转换来实现这一函数: function ntohl ...

  3. # C语言程序设计预备作业

    一.针对老师和学生是怎样的关系的看法 ==首先我认同邹欣老师的看法,下面也是我自己的一点见解.== #### (1)师生在教育内容的教学上结成授受关系 .从教师与学生的社会角色规定意义上看,在知识上, ...

  4. java程序调用存储过程和存储函数

    java程序调用存储过程 jdbcUtil.java文件 package cn.itcast.oracle.utils; import java.sql.Connection; import java ...

  5. JS数组filter()、map()、some()、every()、forEach()、lastIndexOf()、indexOf()实例

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat=&qu ...

  6. 【学习】Zepto与jQuery 差别

    前几天遇到一个项目,需要把jquery全部改成Zepto,当时因为自己没有实际经验,所以没有接.今天查了一下两者究竟有什么区别. 首先看到了这么一篇文章:http://www.bootcss.com/ ...

  7. Xadmin集成富文本编辑器ueditor

    在xadmin中通过自定义插件,实现富文本编辑器,效果如下: 1.首先,pip安装ueditor的Django版本: pip install DjangoUeditor 2.之后需要添加到项目的set ...

  8. 深入浅出:JavaScript作用域链

    1. 什么是作用域 任何程序设计语言都有作用域的概念,简单的说,作用域就是变量的作用范围. 2. 变量的分类和变量作用域的分类 在JavaScript中,变量分为全局变量和局部变量,与此相对应的,变量 ...

  9. PyCharm 2017 官网 下载 安装 设置 配置 (主题 字体 字号) 使用 入门 教程

    一.安装 Python 3.6 首先,要安装好 Python 3.6.如果你还没有安装,可以参考咪博士之前的教程 Python 3.6.3 官网 下载 安装 测试 入门教程 (windows) 二.官 ...

  10. 使用spark与MySQL进行数据交互的方法

    在项目中,遇到一个场景是,需要从Hive数据仓库中拉取数据,进行过滤.裁剪或者聚合之后生成中间结果导入MySQL. 对于这样一个极其普通的离线计算场景,有多种技术选型可以实现.例如,sqoop,MR, ...