这个一个基于资源池模式、Javascript, Typescript友好的抽象资源池工具库。 能够帮助你快速构建一个资源池,以及对资源池进行管理。
支持以下特性:
- 资源池的创建
- 资源获取、释放
- 资源池的扩容、缩容
- 资源池的事件监听
- 资源的事件监听
- 资源异步调度
npm install @cat5th/pool.js
or yarn
yarn add @cat5th/pool.js
创建一个资源池
import { Pool } from '@cat5th/pool.js';
const pool = new Pool(3);
创建一个Web Worker资源池
import { Pool } from '@cat5th/pool.js';
const workerPool = new Pool((created) => {
if (created > 3) {
return undefined;
}
const worker = new Worker('worker.js');
return worker;
});
const limiter = workerPool.limit();
limiter(function() {
// this === worker
this.postMessage('hello');
});
限制请求频率为每秒最多10次
import { limit } from '@cat5th/pool.js';
const request = limit(function() {
const response = await fetch('https://api.github.com');
return response.json();
}, 10, {
minDuration: 1000,
});
for (let i = 0; i < 100; i++) {
request();
}
请查看 example 目录下的例子
import { Pool } from '@cat5th/pool.js';
const create = (created) => {
// 创建资源
return {
// created 为已创建的资源数量
id: created,
};
};
const pool = new Pool(create);
// 或者 以对象的形式创建资源池
const pool = new Pool({
create,
// 初始化资源池大小
initialSize: 10,
// 资源重置函数
reset: (resource) => {
console.log('资源被释放了');
},
});
// 或者 传入 number
const pool = new Pool(10);
// 等效于
const pool = new Pool((created) => {
return created > 10 ? undefined : Object.create(null);
});
// 同步获取资源
const resource = pool.acquire();
// resource?.id === 0
// 当资源池中没有资源时,会返回 `undefined``
// 异步获取资源
const resource = await pool.acquire(true);
// resource.id === 0
// 当资源池中没有资源时,会等待资源池中有资源时才返回
// 异步获取资源可以通过传入 `AbortSignal` 来中断
const controller = new AbortController();
const resource = await pool.acquire(true, controller.signal);
controller.abort();
// 会抛出错误
resource.id === 0
// 释放方法是同步的
pool.release(resource);
// 监听资源池的获取事件
pool.on('create', (resource) => {
console.log(`资源 ${resource.id} 被获取了`);
});
// 监听资源池的释放事件
pool.on('release', (resource) => {
console.log(`资源 ${resource.id} 被释放了`);
});
const limiter = pool.limit();
// 资源限制器是一个执行函数,需要传入一个异步的消费函数,以及它的参数
// 限制器会返回一个 `Promise`,当资源池中有资源时,会执行消费函数
// 当资源池中没有资源时,会等待资源池中有资源时才执行消费函数
const result = await limiter(async function(...args) {
console.log(`当前资源为 ${this.id}`);
// resource.id === 0
// args === [1, 2, 3]
return 1;
}, 1, 2, 3);
// limit 方法支持传入限制器参数
const limiter = pool.limit({
// 消费函数最少执行时间,如果消费函数执行时间小于 `minDuration`,
// 执行会随着消费函数同时结束,但使用的资源会在 `minDuration`` 后释放
minDuration: 1000,
});
// 资源限制器提供了一个 `abort` 方法,可以中断当前的消费函数,使执行返回会抛出错误
limiter.abort(new DOMException('AbortError'));
Pool 实现了 Iterable
接口,可以使用 for...of
进行遍历。
同时 Pool
也实现了 AsyncIterable
接口,可以使用 for await...of
进行异步遍历。
// 遍历资源池里边的资源,同时会获取资源,
// 同步遍历时,如果资源池中没有资源,会退出遍历
for (const resource of pool) {
console.log(resource.id);
}
// 异步遍历时,如果资源池中没有资源,会等待资源的获取
// 所以异步遍历时,不会退出遍历,相当于一个无限循环
for await (const resource of pool) {
console.log(resource.id);
}
Pool 实现了 PromiseLike
接口,可以使用 await
进行等待。
// await pool 意味着等待所有资源都被释放,才会返回
await pool;
是的,cat5th/pool.js
很贴心的提供了一个 pLimit
和 Pool.limit
的方法,它是Pool.prototype.limit
的别名。
import { pLimit } from '@cat5th/pool.js';
// `pLimit`的第一参数为`Pool`构造器的参数,第二个参数为`Pool.prototype.limit`的参数
const limiter = pLimit(10, {
minDuration: 1000,
});
limit
方法是 Pool.limit
的一个包装器,它直接返回一个可执行的函数
import { limit } from '@cat5th/pool.js';
const fn = limit(async function() {
// ...
}, 10, {
minDuration: 1000,
});
fn(...args);
感谢以下项目的启发: