随身笔记
随身笔记

js异步模块以及回调--async.js

js jquery 异步 回调 Deferred promise 地狱回调 地狱 回调

说到js的异步就会让我想到使用requirejs和jquery的$.ajax,和HTML5的异步,之前都有介绍过可以参阅:

jquery内置异步功能简单使用》 《html5异步》 《requirejs教程》 《requirejs模块管理插件简单介绍及案例

 

IE 6+
Opera 15+
Safari 5+
Chrome 30+
Firefox 3.6.28+

 

async.js是为nodejs开发出来的异步编程模块,但是也可以直接用于网页中使用,兼容性可以支持IE6以上。

如果要在nodejs上使用就安装

下载:async.rar

npm install async
<script src="async.min.js"></script>

 

举两个简单例子:

 //同步,只有当前面的函数执行完成后,后面的函数才能执行,都执行完成后才回调成功函数,
如果中途有错误被激活后面的函数也不会执行,立马回调出错误的函数。

async.series([ 
  function (fn) {
     setTimeout(function () {
       $('div').css({ 'background': 'red' });
       fn(null); //在同步时,设置null表示成功,下面的步骤才会执行,null以外的内容表示错误
     }, 3000);
  }, function (fn) {
     console.log(2);
     fn(null);
  }], function (err, sucess) {
     if (err) {
        document.title = '出错,没全部都执行';
     } else if (sucess) {
        document.title = '成功,全部都执行了';
     } 
 });

作用就是为某个函数添加回调函数,这个其实在jquery也能实现。

 

 

//each 
//异步,不管之前的函数有没有执行,后面的函数也能先执行,都执行完成后才进行回调

var items = [    
   function (callback) {
     setTimeout(function () { alert(1); callback() }, 2000);
   },
   function (callback) {
     alert(2);
     callback()
   }
 ];


async.each(items, function (item, callback) {
    (item)(callback);
  }, function () {
    alert('都执行了');
 });


--------------------------------------------------------------------------------------

//异步,eachLimit当作是each的加强版,只是添加了一个limit参数也就是允许同时执行函数的进程数量
//在没有出错的情况下,下面的例子弹出的顺序是 2,3,1,5,4
//你可以理解为一个厕所有2个公共坑位,1和2同时进,3,4,5后面等。2立马就出来,1还迟迟没出来,
//2的位置就让3给用了,3也立马出来,接着4进去,这时刻4和1同时在里面。1终于出来了,
//5立马进去也立马出来,最后4也出来了。

//某个函数中激活错误函数,后面的函数不会运行,错误回调立马被执行


async.eachLimit([ 
   function (callback) {
      setTimeout(function () {
        alert(1);
        callback()
      }, 4000);
   }, function (callback) {
        alert(2);
        callback()
   }, function (callback) {
        alert(3);
        callback()
   }, function (callback) {
        setTimeout(function () {
          alert(4);
          callback()
        }, 5000);
    }, function (callback) {
         alert(5);
         callback()
       }
  ],2, function (item, callback) {
       (item)(callback);
      }, function (err) {
          if (err) {
              alert('有错误到此为止');
          } else {
              alert('都执行完成了');
          }
 });




--------------------------------------------------------------------------------

//eachSeries   
//和each有2点不同,
//1,eachSeries是同步的
//2,一旦某一个函数中的错误被激活,此函数的后面其他函数就不会执行

async.eachSeries([
  function (callback) {
    setTimeout(function () {
       alert(1);
       callback()
    }, 2000);
  }, function (callback) {
       alert(2);
       callback()
  }, function (callback) {
       alert(3);
       callback()
  }
 ], function (item, callback) {
       (item)(callback);
 }, function (err) {
      if (err) {
        alert('有错误到此为止');
      } else {
        alert('都执行完成了');
      }
 });

 

 

// 同步,上一个函数可以传值给下一个函数使用,如果某一个函数错误激活后面的函数也不能执行,之后就是回调
//waterfall 的 tasks 参数只能是数组类型
async.waterfall([
   function (callback) {
      callback(null, 'one', 'two');
   },
   function (arg1, arg2, callback) { //上面的callback传2个参数,要接受的话就设置2个参数
      console.log(arg1 + '--' + arg2); // one--two
      callback(null, 'three','fff','4444');
   },
      function (arg1, arg2, arg3, callback) {//上面的callback传3个参数,要接受的话就设置3个参数
      console.log(arg1 + '--' + arg2 + '--' + arg3); //three--fff--4444
      callback(null, 'done');
   }
 ], function (err, result) {
      if (err) {
          alert('有错误' + err);
      } else {
          alert('都执行了' + result);
      }
 });




//如果希望第一个函数也能接收到其他值的话可以这么写

async.waterfall([
   async.apply(myFirstFunction, 'zero'),
   mySecondFunction,
   myLastFunction,
 ], function (err, result) {
   // result now equals 'done'
 });


 function myFirstFunction(arg1, callback) {
   // 第一个函数接收到zero参数
   callback(null, 'one', 'two');
 }
 function mySecondFunction(arg1, arg2, callback) {
   callback(null, 'three');
 }
 function myLastFunction(arg1, callback) {
   callback(null, 'done');
 }

 

 

 

//异步,如果没激活错误返回的结果是 one,two,thress,thress 是按照之前的顺序排序的,
//跟执行的时间顺序无关。

//如果某个函数有激活错误,错误的回调立马执行,后面的函数依然执行。

async.parallel([
   function (callback) {
      callback(null, 'one');
   },
   function (callback) {
      console.log(22);
      callback(null, 'two');
   }, function (callback) {
      console.log(33);
      callback(null, 'thress');
   }, function (callback) {
      console.log(44);
      callback(null, 'thress');
   }],
 function (err, results) {
     if (err) {
        console.log('错误:'+err);
     } else {
        console.log('成功:' + results);
     }
 });

 

 

 

//批量修改数组内容,功能跟jquery中的map一样

 async.map(['file1', 'file2', 'file3'], function (item, callback) {
     console.log(item); // file1,file2,file3
     callback(null, item + 1);
   }, function (err, results) {
     if (err) {
        console.log(err);
     } else if (results) {
        console.log(results); // ["file11", "file21", "file31"]
     }
 });


扩展功能
mapSeries(arr, iteratee, [callback])
mapLimit(arr, limit, iteratee, [callback])

 

 

//效果就是类似for循环完了之后就回调一个函数

var count = 0;
async.during(
   function (callback) {
     // console.log('当count等于' + count+'时,执行了一些代码'); //代码放这里执行了6次
     return callback(null, count < 5);
   },
   function (callback) {
     count++;
     // console.log('当count等于' + count + '时,执行了一些代码'); //代码放这里执行了5次(推荐放这里)
     document.title = count;
     setTimeout(callback, 1000);
     // console.log(count);
   },
   function (err,sucess) { //第六秒时候执行回调
     if (err) { } else { document.title = 'for循环成功后回调'; }
   }
 );

 

 

//类似for循环,创建对象

var arr = [];
 function createUser(id, callback) {
    callback(null, {  //这里写的对象就是我们要循环创建的
      id: 'user' + id
    })
 }
 // generate 5 users
 async.times(5, function (n, next) {
    createUser(n, function (err, user) {
       console.log(n); //索引
       console.log(user); //对象
       next(err, user)
    })
 }, function (err, users) {
       arr = users;
 });

console.log(arr);

 

 

//同步,设置为1 任意一个函数错误激活后面程序仍然可以运行,都运行完成后回调
//异步,设置>1的数字 任意一个函数错误激活后面程序仍然可以运行,都运行完成后回调

var q = async.queue(function (task, callback) {
   //q.length() //返回还有多少个正在等待的要执行的函数,假如有3个进程,第一个函数必须先执行后才能执行到它,因为他查询的是等待的函数。
   // console.log(q.started); //判断我们定义的这个q对象是否已经开始执行整个程序,true是这个整个程序开始执行了。
  if (task.name == '工人1') {
    setTimeout(function () {
      console.log('hello ' + task.name);
      callback(1);
    }, 3000)
  } else if (task.name == '工人2') {
     setTimeout(function () {
       console.log('hello ' + task.name);
       callback(1);
     }, 3000)
   } else {
      console.log('hello ' + task.name);
      callback();
    }
},2); //这里设置并发数有2以上的就是异步了,如果没设置默认就是1,也就是同步了



 q.drain = function () { //所有的程序都执行完,而且不管成不成功都要执行这里
    console.log('最后这里总要执行');
    // console.log(q.idle()); //默认是false说明程序在执行,如果为true说明程序已经结束了。
 }


 q.empty = function () { //总是在最后一个函数执行完成之前执行。例如,有3个函数,在前2个函数执行完成后就立马执行。
    console.log('总是在最后一个函数执行完成之前执行');
    // console.log(q.idle()); //默认是false说明程序在执行,如果为true说明empty程序已经结束了。
 }


 q.push({ name: '工人1' }, function (err) {
    if (err) {
       console.log('工人1 没完成'); //单进程失败回调
      //ill(); //在此代码后面的所有函数都不会执行,包括q.drain
      //.pause() //此代码后面的,函数暂时停止运行
      //q.paused //true,表示程序暂停 false,表示没暂停 
      // setTimeout(function () { q.resume() }, 13000); //13秒后恢复 q.pause和q.resume配合使用
    } else {
       console.log('工人1 完成'); //单进程成功回调
    }
 });



q.push({ name: '工人2' }, function (err) {
    if (err) {
      console.log('工人2 没完成');
    } else {
      console.log('工人2 完成');
    }
 });



q.push({ name: '工人3' }, function (err) {
    if (err) {
       console.log('工人3 没完成');
    } else {
       console.log('工人3 完成');
    }
 });

 

 

 

https://github.com/caolan/async

http://www.easyui.info/archives/1788.html

https://cnodejs.org/topic/54acfbb5ce87bace2444cbfb

 

 

 

随身笔记

js异步模块以及回调--async.js
js jquery 异步 回调 Deferred promise 地狱回调 地狱 回调 说到js的异步就会让我想到使用requirejs和jquery的$.ajax,和HTML5的异步,之前都有介绍过可以参阅: 《jquery内置异步…
扫描二维码继续阅读
2016-03-08