-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
476 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/** | ||
* 一个indexdb的增删改查 | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,71 +1,138 @@ | ||
/** | ||
* 一个队列执行器: | ||
* 任务可以支持有优先级的任务, | ||
* 批量执行,清空任务列表 | ||
* 生产者、消费者、优先级队列 | ||
* 生产者生产到优先级任务,任务指定消费者消费 | ||
*/ | ||
import { genAutoIdString } from '..'; | ||
type Task = { | ||
id: number; | ||
priority: number; | ||
consumerId: number; | ||
}; | ||
|
||
/** 任务信息 */ | ||
export class Task<T> { | ||
message: T; | ||
class ProducerManager { | ||
private producers: Map<number, Producer>; | ||
|
||
constructor(message: T) { | ||
this.message = message; | ||
constructor() { | ||
this.producers = new Map(); | ||
} | ||
|
||
registerProducer(producerId: number) { | ||
const producer = new Producer(producerId); | ||
this.producers.set(producerId, producer); | ||
return producer; | ||
} | ||
|
||
getProducer(producerId: number) { | ||
return this.producers.get(producerId) || null; | ||
} | ||
} | ||
|
||
/** 任务优先级队列 */ | ||
export class MessageQueue<T> { | ||
/** 任务队列 */ | ||
queue: Map<string, Task<T>> = new Map(); | ||
/** 执行器 */ | ||
executor: (token: string, task: Task<T>) => void; | ||
/** 是否是优先级队列 */ | ||
is_priority_queue: boolean = false; | ||
|
||
constructor({ | ||
executor, | ||
is_priority_queue | ||
}: { | ||
executor: (task: Task<T>) => void; | ||
is_priority_queue?: boolean; | ||
}) { | ||
this.is_priority_queue = is_priority_queue ?? false; | ||
this.queue = new Map(); | ||
this.executor = (token: string, task: Task<T>) => { | ||
executor(task); | ||
this.delete(token); | ||
}; | ||
class ConsumerManager { | ||
private consumers: Map<number, Consumer>; | ||
|
||
constructor() { | ||
this.consumers = new Map(); | ||
} | ||
|
||
registerConsumer(consumerId: number) { | ||
const consumer = new Consumer(consumerId); | ||
this.consumers.set(consumerId, consumer); | ||
return consumer; | ||
} | ||
|
||
getConsumer(consumerId: number) { | ||
return this.consumers.get(consumerId) || null; | ||
} | ||
} | ||
|
||
class PriorityQueue { | ||
private tasks: Task[]; | ||
|
||
constructor() { | ||
this.tasks = []; | ||
} | ||
|
||
enqueue(task: Task) { | ||
this.tasks.push(task); | ||
this.tasks.sort((a, b) => b.priority - a.priority); | ||
} | ||
|
||
dequeue() { | ||
return this.tasks.shift() || null; | ||
} | ||
|
||
/** 添加任务 */ | ||
add(task: Task<T>) { | ||
const token = genAutoIdString(); | ||
this.queue.set(token, task); | ||
return token; | ||
isEmpty() { | ||
return this.tasks.length === 0; | ||
} | ||
} | ||
|
||
class Producer { | ||
private producerId: number; | ||
private queue: PriorityQueue; | ||
|
||
/** 删除任务 */ | ||
delete(token: string) { | ||
this.queue.delete(token); | ||
constructor(producerId: number) { | ||
this.producerId = producerId; | ||
this.queue = new PriorityQueue(); | ||
} | ||
|
||
/** 运行任务 */ | ||
run() { | ||
let sort_queue = this.is_priority_queue | ||
? Array.from(this.queue.keys()).sort((a_token, b_token) => { | ||
const a = this.queue.get(a_token)!; | ||
const b = this.queue.get(b_token)!; | ||
const a_priority = (a.message as any)?.priority ?? 0; | ||
const b_priority = (b.message as any)?.priority ?? 0; | ||
return a_priority > b_priority ? -1 : 1; | ||
}) | ||
: Array.from(this.queue.keys()); | ||
produceTask(priority: number, consumerId: number) { | ||
const task: Task = { | ||
id: Date.now(), | ||
priority, | ||
consumerId | ||
}; | ||
|
||
this.queue.enqueue(task); | ||
} | ||
|
||
let token = sort_queue.shift(); | ||
while (token) { | ||
this.executor(token, this.queue.get(token)!); | ||
token = sort_queue.shift(); | ||
consumeTask() { | ||
if (!this.queue.isEmpty()) { | ||
return this.queue.dequeue(); | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
|
||
class Consumer { | ||
private consumerId: number; | ||
|
||
constructor(consumerId: number) { | ||
this.consumerId = consumerId; | ||
} | ||
|
||
consumeTask(task: Task) { | ||
console.log(`Consumer ${this.consumerId} is consuming task:`, task); | ||
// 执行任务的消费逻辑 | ||
} | ||
} | ||
|
||
// 示例用法 | ||
const producerManager = new ProducerManager(); | ||
const consumerManager = new ConsumerManager(); | ||
|
||
const producer1 = producerManager.registerProducer(1); | ||
const producer2 = producerManager.registerProducer(2); | ||
|
||
const consumer1 = consumerManager.registerConsumer(1); | ||
const consumer2 = consumerManager.registerConsumer(2); | ||
|
||
producer1.produceTask(2, consumer1.consumerId); | ||
producer2.produceTask(1, consumer2.consumerId); | ||
producer1.produceTask(3, consumer2.consumerId); | ||
producer2.produceTask(1, consumer1.consumerId); | ||
|
||
let task = producer1.consumeTask(); | ||
if (task) { | ||
const consumer = consumerManager.getConsumer(task.consumerId); | ||
if (consumer) { | ||
consumer.consumeTask(task); | ||
} | ||
} | ||
|
||
task = producer2.consumeTask(); | ||
if (task) { | ||
const consumer = consumerManager.getConsumer(task.consumerId); | ||
if (consumer) { | ||
consumer.consumeTask(task); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/** 数值类型 */ | ||
export function isNumber(num: any) { | ||
return !isNaN(Number(num)); | ||
} | ||
|
||
/** 格式化十进制四舍五入保留小数位 */ | ||
export function formatFloatNumber(num: number, precision: number) { | ||
return Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision); | ||
} | ||
|
||
/* 格式化数值为固定小数位数 | ||
>>> toFixedNumber(0.4517, 1) | ||
0.5 | ||
*/ | ||
export function toFixedNumber(num: number, fraction: number): number { | ||
return Number(Number(num).toFixed(fraction)); | ||
} | ||
|
||
/* 格式化数值为百分比,支持设定小数位数 | ||
>>> formatNumberToPercent(0.4517, 1) | ||
45.2% | ||
*/ | ||
export function formatNumberToPercentString( | ||
data: number | '' | '0' | 'null' | '-' | '(NULL)', | ||
fraction?: number | ||
): string { | ||
if (!isNumber(data) || data === '') { | ||
return data as string; | ||
} | ||
data = (data as number) * 100; | ||
|
||
// 小数位数 | ||
if (fraction != null) { | ||
data = data = toFixedNumber(data, fraction!); | ||
} | ||
|
||
return data + '%'; | ||
} | ||
|
||
/** | ||
* 千分位 | ||
* @param num 数值 | ||
* @returns | ||
*/ | ||
export function getThousandthSeparatedNumber(num: any) { | ||
if (!isNumber(num)) { | ||
return num; | ||
} | ||
const sep = function (str: string) { | ||
return (str + '').replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,'); | ||
}; | ||
num = num + ''; | ||
num = num.split('.'); | ||
const num_0 = sep(num[0]); | ||
if (num.length === 1) { | ||
return num_0; | ||
} | ||
return num_0 + '.' + num[1]; | ||
} | ||
|
||
/** 单位 */ | ||
export enum Unit { | ||
'无' = '无', | ||
'K' = 'K', | ||
'千' = '千', | ||
'万' = '万', | ||
'亿' = '亿', | ||
'兆' = '兆', | ||
'M' = 'M', | ||
'百万' = '百万', | ||
'B' = 'B' | ||
} | ||
/** | ||
* 格式化单位 | ||
* @param num 数值 | ||
* @param unit_value 单位 | ||
* @param fraction 小数位数 | ||
* @returns | ||
*/ | ||
export function formatNumberUnit( | ||
num: number, | ||
unit_value: Unit, | ||
fraction?: number | ||
) { | ||
switch (unit_value) { | ||
case '无': | ||
break; | ||
|
||
case 'K': | ||
case '千': | ||
num = num / 1000; | ||
break; | ||
|
||
case '万': | ||
num = num / 10000; | ||
break; | ||
|
||
case 'M': | ||
case '百万': | ||
num = num / 100_0000; | ||
break; | ||
|
||
case '亿': | ||
num = num / 1_0000_0000; | ||
break; | ||
|
||
case 'B': | ||
num = num / 10_0000_0000; | ||
break; | ||
} | ||
|
||
if (fraction != null) { | ||
num = toFixedNumber(num, fraction!); | ||
} | ||
|
||
return num; | ||
} | ||
|
||
// 将数字转的为人眼好识别的文字 | ||
export function readableNumbers(num: number, base = 1000): string { | ||
if (isNaN(num * 1)) { | ||
return num.toString(); | ||
} | ||
|
||
const neg = num < 0; | ||
const units = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']; | ||
|
||
if (neg) { | ||
num = -num; | ||
} | ||
|
||
if (num < 1) { | ||
return (neg ? '-' : '') + num; | ||
} | ||
|
||
const exponent = Math.min( | ||
Math.floor(Math.log(num) / Math.log(base)), | ||
units.length - 1 | ||
); | ||
|
||
num = Number((num / Math.pow(base, exponent)).toFixed(2)); | ||
|
||
const unit = units[exponent]; | ||
|
||
return (neg ? '-' : '') + num + unit; | ||
} |
Oops, something went wrong.