12 changed files with 255 additions and 5 deletions
@ -0,0 +1,6 @@ |
|||
import { isArray } from "@xyx-utils/core/utils" |
|||
|
|||
export function demote(arr: any[], result: any[] = []) { |
|||
arr.forEach((i) => (isArray(i) ? demote(i, result) : result.push(i))) |
|||
return result |
|||
} |
@ -0,0 +1,4 @@ |
|||
|
|||
export * from "./random" |
|||
export * from "./demote" |
|||
export * from "./uniq" |
@ -0,0 +1,4 @@ |
|||
|
|||
export function random(arr: any[]) { |
|||
return arr.sort(() => Math.random() - 0.5) |
|||
} |
@ -0,0 +1,4 @@ |
|||
|
|||
export function uniq(arr: any[]) { |
|||
return Array.from(new Set(arr)) |
|||
} |
@ -0,0 +1,128 @@ |
|||
/** |
|||
* 任务执行状态枚举类 |
|||
* @type {{INIT: number, RUNNING: number, FINISH: number}} |
|||
*/ |
|||
const enum TaskStatusEnum { |
|||
INIT = -1, //初始化
|
|||
RUNNING = 0, //执行中
|
|||
FINISH = 1, //已完成
|
|||
} |
|||
|
|||
type ITask = (end: Function) => void; |
|||
|
|||
/** |
|||
* 任务单元 |
|||
* @param taskId 任务id |
|||
* @param task 任务函数 |
|||
* @param group 任务组对象 |
|||
* @constructor |
|||
*/ |
|||
class TaskUnit { |
|||
taskId: number; |
|||
status: TaskStatusEnum; |
|||
task: ITask; |
|||
private group: TaskGroup; |
|||
|
|||
constructor(taskId: number, task: ITask, group: any) { |
|||
this.taskId = taskId; //任务唯一标识,暂时没用到
|
|||
this.status = TaskStatusEnum.INIT; //执行状态:-1初始化 0执行中 1已完成
|
|||
this.task = task; //任务内容
|
|||
this.group = group; // 任务组对象
|
|||
} |
|||
|
|||
execute() { |
|||
this.status = TaskStatusEnum.RUNNING; |
|||
const end = () => this.end(); |
|||
this.task(end); |
|||
} |
|||
|
|||
end() { |
|||
if (this.status === TaskStatusEnum.RUNNING) { |
|||
this.status = TaskStatusEnum.FINISH; |
|||
this.group.check(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
class TaskGroup { |
|||
nextGroup: TaskGroup | null = null; |
|||
taskList: TaskUnit[] = []; |
|||
|
|||
constructor() {} |
|||
add(task: TaskUnit) { |
|||
this.taskList.push(task); |
|||
} |
|||
setNextGroup(group: TaskGroup) { |
|||
this.nextGroup = group; |
|||
} |
|||
start() { |
|||
for (let i = 0; i < this.taskList.length; i++) { |
|||
const task = this.taskList[i]; |
|||
if (task.status === TaskStatusEnum.INIT) { |
|||
task.execute(); //执行
|
|||
} |
|||
} |
|||
} |
|||
check() { |
|||
for (let i = 0; i < this.taskList.length; i++) { |
|||
if (this.taskList[i].status !== TaskStatusEnum.FINISH) { |
|||
return; //发现还有任务没有执行完成
|
|||
} |
|||
} |
|||
//任务全部执行完成,进行下一个任务组
|
|||
this.taskList = []; //清空当前任务组,让这些任务尽快回收
|
|||
if (this.nextGroup) { |
|||
let nextGroupTemp = this.nextGroup; |
|||
nextGroupTemp.start(); |
|||
this.nextGroup = null; //取消引用,让当前任务组尽快回收
|
|||
} |
|||
} |
|||
} |
|||
|
|||
export class asyncController<T extends ITask> { |
|||
queue: TaskGroup[] = []; |
|||
nowTaskGroup: TaskGroup | null = null; |
|||
startCount: number = 0; |
|||
|
|||
/** |
|||
* 调用该函数表示添加并行任务 |
|||
* @param task 任务 |
|||
*/ |
|||
and(task: T) { |
|||
if (this.nowTaskGroup == null) { |
|||
this.nowTaskGroup = new TaskGroup(); |
|||
} |
|||
this.nowTaskGroup.add(new TaskUnit(++this.startCount, task, this.nowTaskGroup)); |
|||
return this; |
|||
} |
|||
/** |
|||
* 调用该函数表示添加串行任务 |
|||
* @param task 任务 |
|||
*/ |
|||
next(task: T) { |
|||
if (this.nowTaskGroup != null) this.queue.push(this.nowTaskGroup); //防止上一个添加的任务是并行的
|
|||
this.nowTaskGroup = new TaskGroup(); |
|||
this.nowTaskGroup.add(new TaskUnit(++this.startCount, task, this.nowTaskGroup)); |
|||
this.queue.push(this.nowTaskGroup); |
|||
this.nowTaskGroup = null; //当前任务添加结束清空
|
|||
return this; |
|||
} |
|||
/** |
|||
* 调用该函数表示任务添加完毕,开始执行任务 |
|||
* @param endTask 任务全部结束后回调 |
|||
*/ |
|||
finish = (endTask: T) => { |
|||
if (this.nowTaskGroup != null) this.queue.push(this.nowTaskGroup); |
|||
this.nowTaskGroup = new TaskGroup(); |
|||
this.nowTaskGroup.add(new TaskUnit(++this.startCount, endTask, this.nowTaskGroup)); |
|||
this.queue.push(this.nowTaskGroup); |
|||
this.nowTaskGroup = null; //当前任务添加结束清空
|
|||
|
|||
//组装成单向链表
|
|||
for (let i = 0; i < this.queue.length - 1; i++) { |
|||
this.queue[i].setNextGroup(this.queue[i + 1]); |
|||
} |
|||
this.queue[0].start(); //启动链表首个任务组
|
|||
this.queue = []; //清空任务,为下一波任务做准备
|
|||
}; |
|||
} |
@ -0,0 +1,8 @@ |
|||
--- |
|||
title: asyncController |
|||
category: 异步控制器 |
|||
--- |
|||
|
|||
Demo: |
|||
|
|||
<preview path="./index.vue" title="@niu-tools/core" description="asyncController"></preview> |
@ -0,0 +1,70 @@ |
|||
<script setup lang="ts"> |
|||
// @ts-nocheck |
|||
import { ref } from 'vue' |
|||
import { asyncController as Controller } from "@xyx-utils/core" |
|||
|
|||
const outout: string[] = ref([]) |
|||
|
|||
console.log = (str) => { |
|||
outout.value.push(str) |
|||
} |
|||
const controller = new Controller(); |
|||
function run() { |
|||
outout.value = [] |
|||
controller.and(end => { |
|||
setTimeout(() => { |
|||
console.log("并行1") |
|||
end(); |
|||
}, 2000); |
|||
}).and(end => { |
|||
setTimeout(() => { |
|||
console.log("并行2") |
|||
end(); |
|||
}, 2000); |
|||
}).and(end => { |
|||
setTimeout(() => { |
|||
console.log("并行3") |
|||
end(); |
|||
}, 2000); |
|||
}).next(end => { |
|||
setTimeout(() => { |
|||
console.log("串行1") |
|||
end(); |
|||
}, 2000); |
|||
}).next(end => { |
|||
setTimeout(() => { |
|||
console.log("串行2") |
|||
end(); |
|||
}, 2000); |
|||
}).and(end => { |
|||
setTimeout(() => { |
|||
console.log("并行4") |
|||
end(); |
|||
}, 2000); |
|||
}).and(end => { |
|||
setTimeout(() => { |
|||
console.log("并行5") |
|||
end(); |
|||
}, 2000); |
|||
}).next(end => { |
|||
setTimeout(() => { |
|||
console.log("串行3") |
|||
end(); |
|||
}, 2000); |
|||
}).finish(() => { |
|||
setTimeout(() => { |
|||
console.log("结束") |
|||
}, 2000); |
|||
}) |
|||
} |
|||
</script> |
|||
|
|||
<template> |
|||
<div> |
|||
<button @click="run">运行</button> |
|||
<div>输出:</div> |
|||
<div v-for="i in outout"> |
|||
{{ i }} |
|||
</div> |
|||
</div> |
|||
</template> |
@ -0,0 +1,2 @@ |
|||
|
|||
export * from "./asyncController" |
@ -0,0 +1,4 @@ |
|||
|
|||
export function isArray(arr) { |
|||
return Array.isArray(arr) |
|||
} |
Loading…
Reference in new issue