新轮子: 异步控制库processControl.js 5分钟入手
发布于 7 年前 作者 yongningfu 4918 次浏览 来自 分享

processControl.js

js异步解决方案

js异步解决方案已经很多了,各家都有各家的好处

受到gulp的api,和koa, eventproxy的等启发,决定造一个新轮子

这套api怎么玩?

非常简单, 你只需要定义一个 task, 系统会自动的安装task的顺序执行 并且可以传递参数

一共只有四个api

api 说明
ProcessControl 用于创建一个流程控制
task 定义一个任务
next 用户使用next控制task的执行和任务直接的数据传递
run 让所有的任务按顺序run
UtilsConcurrentTasks 提供的异步并发访问工具

目前实现的功能:

  • 任务的异常按流程执行
  • 提供异步并发访问
  • 任务间的数据传递

todo:

  • 模块打包
  • 增加web 链接数据库的demo
  • 改进文档
  • 测试分离
  • 还有其他等等

注意 processControl 并不会帮你捕获一些异常,在定义任务的时候,你可以完全自己处理,而不是 交个processContro处理,因为没必要,而且processControl本身就单纯的想提高一个控制流服务, 比如给出的并发处理 就把它当成第三方加入processControl, 而不让它参与对象状态的维持(其实就是里面 不出现this)

看 demo

//启动一个流程控制
//注意: next必须放在函数结束末尾

var processControl = new ProcessControl()

processControl.task("task1", function(next, firstData) {

	setTimeout(function() {
		console.log('task1')
		console.log(firstData.data)
		next(true)
	}, 1000)
})

processControl.task("task2", function(next) {

	setTimeout(function() {
		console.log('task2')
		next(true)
	}, 1000)
})


//并入并发的用法
// processControl.concurrentTasks 只是我们提供的方便开发者容易调用的并发api
// 在流程控制中 需要将其用task 接入

processControl.task('concurrentTasks', function(next) {

	// concurrentTask1, concurrentTask2, concurrentTask3 为一个个异步函数 结果按
	//顺序返回数组
	processControl.UtilsConcurrentTasks(concurrentTask1, concurrentTask2, concurrentTask3, function(err, data) {
			if (err) {
				throw 'concurrentTasks error'
				next(false)
			} else {
				console.log(data)
				next(true, data)
			}
	})
})

processControl.task("task3", function(next, receiveDataFromLastTask) {

	console.log(receiveDataFromLastTask)

	for (var i = 0; i < 1000000; i++) {
		var j = j * 2
	}
	console.log('task3')
	next(true, {"data": "task3' data"})
})


processControl.task("task4", function(next, receiveDataFromLastTask) {

	for (var i = 0; i < 1000000; i++) {
		var j = j * 2
	}
	console.log('task4')
	console.log('the data from task3', receiveDataFromLastTask.data)
	next(true)
	// next(true)
})

processControl.run({"data": "these are first task's data"})

补充上面的未定义函数


function concurrentTask1(callback) {
	setTimeout(function() {callback(null, {"aa":11})}, 2000)
}


//整和其他异步方访问库的例子
function concurrentTask2(callback) {

	var fs = require('fs')

	// fs.readFile('test.txt', "utf8", callback)
	fs.readFile('test.txt', "utf8", function(err, data) {
		if (err) callback(err)
		else callback(null, data.toString())
	})
}

function concurrentTask3(callback) {
	setTimeout(function() {callback(null, {"aa":33})}, 100)
}

异步完全变成成同步编程了 喜欢的话 欢迎star 注意:

  • 如果建立一个流程对象,这个对象对象在运行的还没结束的时候,又执行run,它会阻止后面的执行, 继续把之前的执行完成,当然执行当前任务完成后,在继续执行是可以的
  • 如果需要同时控制对个流程,那么就建立多个processControl对象

测试结果

result.gif 源码

19 回复

没讲出和promise对比有什么优点

特别是bluebird的promise

@AnzerWall 谢谢回复 至少使用起来比promise简单的多,而且promise的话,写多了一点,会发现其实代码也很不好看,或者读者根本不知道你下一个then是干什么的, processControl是基于任务描述型的,每个任务都对于读者来说,都非常容易知道,它想干嘛。

@AnzerWall 代码看起来 ,也基本是同步的了

在大部分的api都是promise base的现在基本没什么实用价值

@yejiayu 谢谢回复,伤心,但目标是 要做 不用es6 7 promise ,最好用的异步流程控制 From Noder

支持原创,代码顺序不太友好, thenjs处理的更好一些,

来自酷炫的 CNodeMD

@dbit-xia 感谢支持 其实就是不喜欢链式调用才写这个的

我就觉得回调最多3层,没太乱,就像for循环3层差不多,多了就像for循环一样,代码有问题吧,而且我代码写得少,没见过4层的回调= =

@autumnQH 这个问题可以具体说的详细一点,js异步本身就是层层嵌套的,只是目前的解决方案都只是如何把嵌套分离而已。基本逻辑就是 数据的获取和业务逻辑分离。至于你说的代码有问题可以具体提出,可以一起讨论讨论

@autumnQH 而且你说的 4层回调 不会就是4个任务吧?

先查A表,查出来再根据A表的某个值查B表,再根据B表某个值查C表…(应该是这样吧…)

@autumnQH 你说的是代码执行流程 但是你的for循环的例子指的是代码格式 如果是代码格式的话 没4层嵌套 如果是执行流程的话 为了能异步控制流程 只能是嵌套回调 调用 除非是用协程 但是又因为控制的代码大多数是异步的 所以实际栈的层数不多 From Noder

回到顶部