Вы можете сделать что-то вроде этого.
Примечание - этот код может быть написан более оптимизированным способом. это просто для того, чтобы дать представление.
let operation = (operation, time) => () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, time);
});
};
let op1 = operation("op1", 10000);
let op2 = operation("op2", 2000);
let op3 = operation("op3", 2000);
let op4 = operation("op4", 1000);
let op5 = operation("op5", 5000);
const operations = [
{name: "op1", operation: op1, resource: "R1", startedAt: 0},
{name: "op2", operation: op2, resource: "R2", startedAt: 0},
{name: "op3", operation: op3, resource: "R1", startedAt: 0},
{name: "op4", operation: op4, resource: "R4", startedAt: 0},
{name: "op5", operation: op5, resource: "R5", startedAt: 0}
];
let resources = {
"R1": {
isAvailable: true,
queue: []
},
"R2": {
isAvailable: true,
queue: []
},
"R3": {
isAvailable: true,
queue: []
},
"R4": {
isAvailable: true,
queue: []
},
"R5": {
isAvailable: true,
queue: []
},
};
async function operationExecutor(operation) {
if (operation.startedAt === 0) {
operation.startedAt = performance.now();
}
if (!resources[operation.resource].isAvailable) {
console.log("Operation", operation.name, "waiting for Resource", operation.resource);
resources[operation.resource].queue.push(operation);
} else {
console.log("Operation Started", operation.name);
resources[operation.resource].isAvailable = false;
console.log("Resource locked", operation.resource);
await operation.operation();
const t1 = performance.now();
console.log("Resource released", operation.resource);
resources[operation.resource].isAvailable = true;
console.log("Operation Completed", operation.name, `in ${(t1 - operation.startedAt).toFixed(2)} milliseconds`);
if (Array.isArray(resources[operation.resource].queue) && resources[operation.resource].queue.length > 0) {
operationExecutor(resources[operation.resource].queue.splice(0, 1)[0]);
}
}
}
for (let i = 0; i < operations.length; i++) {
(operationExecutor)(operations[i]);
}