FED

©FrontEndDev.org
2015 - 2024
web@2.23.0 api@2.21.1

node 模块 howdo-异步流程控制

1、生活例子

例1:我一边听歌,一边阅读10次课文。在我们的大脑里,现在已经分配了11个并行任务(一起做):

  • 任务1:听歌。
  • 任务2-11:阅读10次课文。

这11个任务是可以同时进行的。

例2:我打开书本,然后阅读10次课文。在我们的大脑里,现在已经分配了11个串行任务(跟着做):

  • 任务1:打开书本。
  • 任务2:在打开书本之后,阅读10次课文。

在现实生活中,我们不能处理大量的并行和串行任务,我们需要手动将我们的任务肢解开来,比如从早上到晚上这一天的时间,我们需要做很多事情。我们需要在大脑里将任务按照某种顺序分解开来。比如上午看书,下午打球,这两件事是跟着做的,只有看完书之后才可以打球。然后上午先看语文,然后看数学,这也是一个串行任务(跟着做)。下午一边打球,一边和朋友聊天,这两件事是并行的,是一起做的。

计算机的事情,需要我们人为去分配任务,我们可以参考我们的现实生活,把需要做的事情,按照并行和串行分开,简化分配任务,然后小任务合成大任务。这样,一件复杂的事情也可以按照分配情况预期完成。

2、howdo的API

howdo的思想和上面说的生活例子是一样的道理,把任务按照执行类型(一起做的还是跟着做的)分类开来,然后再去分配任务。howdo的API非常的简洁,只有#task#each#follow#together四个,而且使用非常简单,可以链式混合使用,其中#follow#together是链式终点。

2.1、#task 分配单次任务

分配单次任务是一个计划过程,就是在任务执行之前约定好怎么做。

var howdo = require('howdo');
 
howdo
// 单次任务1
.task(funtion(next) {
	next(null, 1, 2);
})
// 单次任务2
.task(funtion(next, ret1, ret2) {
	// ret1 = 1
	// ret2 = 2
	next(null, ret1 + ret2);
})
// 跟着做
.follow(function(err, ret3){
	// ret3 = 3
});
 
 
howdo
// 单次任务1
.task(funtion(done) {
	done(null, 1, 2);
})
// 单次任务2
.task(funtion(done) {
	done(null, 3);
})
// 一起做
.together(function(err, ret1, ret2, ret3) {
	// ret1 = 1
	// ret2 = 2
	// ret3 = 3
});

#task是可以链式操作的,每当开始执行task都会实例化一次新的任务计划。如果链式不得不断开的话,请先缓存起来。

2.1、#each 分配批量任务

分配批量任务也是一个计划过程,就是在任务执行之前约定好怎么做。

var howdo = require('howdo');
 
howdo
// 批量任务1
.each([1, 2, 3], funtion(key, val, next) {
    next(err, val);
})
// 批量任务2
.each({
    a: 4,
    b: 5,
    c: 6,
}, funtion(key, val, next, ret1) {
    next(err, ret1 + val);
})
// 跟着做
.follow(function(err, ret) {
    // ret = 18 = 3 + 4 + 5 + 6
});
 
 
howdo
// 批量任务1
.each([1, 2, 3], funtion(key, val, done) {
    done(err, val);
})
// 批量任务2
.each({
    a: 4,
    b: 5,
    c: 6,
}, funtion(key, val, done) {
    done(err, val);
})
// 一起做
.together(function(err, ret1, ret2, ret3, ret4, ret5, ret6) {
    // ret1 = 1
    // ret2 = 2
    // ret3 = 3
    // ret4 = 4
    // ret5 = 5
    // ret6 = 6
});

#each也是链式操作的,可以与#task合起来用。

2.3、#follow 跟着做

任务分配好后,任务跟着做,只回调最后一次结果。

2.4、#together 一起做

任务分配好后,任务一起做,回调任务顺序的所有结果。

3、howdo的一些注意点

3.1、next参数

和nodejs的约定一样,next是回调函数,第1个参数始终为error对象,为空表示无错误,不为空时该参数必须为Error对象的实例。next意思是把当前任务结果传递给下一个任务。格式为:

howdo.task(function(next) {
    next(err, ret1, ret2, ret3, ...);
});

3.2、done参数

与next参数格式一致。它的使用场合是,把当前任务结果提交给总结。例如,大家把作业都统一交给班长,这个交作业的过程为done。格式为:

howdo.task(function(done) {
    done(err, ret1, ret2, ret3, ...);
});

如果done的结果非常的多,那么在最后所有结果合并的时候,可能造成识别困难,因此推荐每一个任务只提交1个结果:

howdo.task(function(done) {
    done(err, ret);
});

3.3、each参数

each是和task同级的,不同的作用是,each可以一次性定义批量任务。这些批量任务是可以并行也可以是串行的,非常的实用。each使用比较复杂,参数也非常的多,参数有:

howdo.each(object, function(key, val, next, prevRet1, prevRet2) {
    next(err, ret1, ret2, ret3, ...);
});
 
howdo.each(object, function(key, val, done) {
    done(err, ret1, ret2, ret3, ...);
});
```

- 参数1:是需要each的对象,可以是数组和对象
- 参数2:是一个回调函数
- 参数1:键
- 参数2:值
- 参数3:可以是`next`或者`done`

剩余参数:如果是`follow`的话,那么剩下的参数为上一次传递下来的结果


## 3.4、follow参数

`follow`是链式终点,它也是回调函数,因此第一个参数为错误标记,剩余参数为最后一次任务的结果。
```
.follow(function(err, ret1, ret2, ret3) {
    // ret1 = 4
    // ret2 = 5
    // ret3 = 6
});
```

如第1次任务结果为1,第2次任务结果为2、3,最后第3次任务结果为__4、5、6__,那么__ret1、ret2、ret3分别为4、5和6__。

## 3.5、together参数

`together`也是链式终点,它也是回调函数,因此第一个参数为错误标记,剩余参数为所有任务的结果集合。
```
.totether(function(err, ret1, ret2, ret3, ret4, ret5, ret6) {
    // ret1 = 1
    // ret2 = 2
    // ret3 = 3
    // ret4 = 4
    // ret5 = 5
    // ret6 = 6
});
```

如第1次任务结果为1,第2次任务结果为2、3,最后第3次任务结果为__4、5、6__,那么__ret1、ret2、ret3、ret4、ret5、ret6分别为1、2、3、4、5和6__。