Skip to content

queueByKey

按键对异步函数调用进行排队,确保每个键的顺序执行

215 bytes
since v12.6.0

使用方法

包装异步函数以确保具有相同键的调用排队并顺序执行,而具有不同键的调用可以并行运行。这对于防止同一逻辑组(如用户 ID 或资源 ID)的操作不重叠时的竞争条件很有用。

import * as _ from "radashi";
const updateUser = async (userId: string, data: object) => {
// 模拟不应为同一用户重叠的API调用
const response = await fetch(`/api/users/${userId}`, {
method: "POST",
body: JSON.stringify(data),
});
return response.json();
};
const queuedUpdate = _.queueByKey(updateUser, (userId) => userId);
// 这些将为user123顺序运行
queuedUpdate("user123", { name: "Alice" });
queuedUpdate("user123", { age: 30 });
// 这与user123的队列并行运行
queuedUpdate("user456", { name: "Bob" });

主要特性

  • 每个键顺序: 具有相同键的操作依次执行
  • 跨键并行: 具有不同键的操作并发运行
  • 错误处理: 错误被正确传播且不会破坏队列
  • 内存高效: 队列在空时自动清理
  • 类型安全: 完全支持 TypeScript 的泛型类型

高级示例

import * as _ from "radashi";
// 必须按表序列化的数据库操作
const dbOperation = async (table: string, operation: string, data: any) => {
console.log(`Starting ${operation} on ${table}`);
await new Promise((resolve) => setTimeout(resolve, 100)); // 模拟工作
console.log(`Completed ${operation} on ${table}`);
return { table, operation, data };
};
// 按表名排队以防止同一表上的并发操作
const queuedDbOp = _.queueByKey(
dbOperation,
(table) => table // 键函数提取表名
);
// 这些在'users'表上的操作将顺序运行
queuedDbOp("users", "insert", { name: "Alice" });
queuedDbOp("users", "update", { id: 1, name: "Bob" });
queuedDbOp("users", "delete", { id: 2 });
// 这些在'orders'表上的操作与'users'操作并行运行
queuedDbOp("orders", "insert", { userId: 1, total: 100 });
queuedDbOp("orders", "update", { id: 1, status: "shipped" });

错误处理

包装函数的错误被正确传播给调用者,队列继续处理后续调用:

import * as _ from "radashi";
const riskyOperation = async (id: string, shouldFail: boolean) => {
if (shouldFail) {
throw new Error(`Operation failed for ${id}`);
}
return `Success for ${id}`;
};
const queuedRiskyOp = _.queueByKey(riskyOperation, (id) => id);
try {
await queuedRiskyOp("user1", true); // 这将抛出错误
} catch (error) {
console.log(error.message); // "Operation failed for user1"
}
// 队列正常继续
const result = await queuedRiskyOp("user1", false);
console.log(result); // "Success for user1"