Reputation: 5646
I am trying to implement a ticket queue system, where by default it would have 3 different queues to holder tickets that are of severity 1, severity 2, and severity 3 respectively. And I have a method getTicketAtHighestSeverity
in it that returns the oldest ticket in the highest severity queue, so it starts at the first queue and looks for the first item in the queue and moves onto the next queue if the current queue is empty and another method getTicketBySeverity
to iterate through all the all queues return the ticket starting at the highest severity
Here is my implementation.
class ticketQueues {
constructor(numOfQueues = 3) {
this.queues = Array.from({length: numOfQueues}).fill([])
}
addSev1(ticket) {
this.queues[0].push(ticket)
}
addSev2(ticket) {
this.queues[1].push(ticket)
}
addSev3(ticket) {
this.queues[2].push(ticket)
}
*getTicketBySeverity() {
for(const queue of this.queues) {
for(const ticket of queue) {
yield ticket
}
}
return null
}
getTicketAtHighestSeverity() {
for(const queue of this.queues) {
for(const ticket of queue) {
return ticket
}
}
return null
}
}
However it seems like getTicketBySeverity
is not working properly.
const queues = new ticketQueues()
queues.addSev1({timestamp: Date(), name: 't1'})
queues.addSev2({timestamp: Date(), name: 't2'})
queues.addSev3({timestamp: Date(), name: 't3'})
for(let i = 2; i >= 0; i--) {
console.log(queues.getTicketBySeverity().next().value) // 🚨 this keeps returning the first item from the queue
}
Because it is not moving to the next ticket as it only returns the first ticket. The reason I chose Generator to implement this method is that I wanted to take advantage of the lazy evaluation model because the data set can be huge, I don't want to necessarily have to get all of the tickets all at once.
Can someone fix my implementation with getTicketBySeverity
. And any suggestions about the naming here? I feel like the naming here i.e. getTicketBySeverity
and getTicketAtHighestSeverity
might not be the best choice. Also, feel free to comment on my usage of Generator here if you think this might not be a legit use case for that.
Upvotes: 2
Views: 1129
Reputation: 371138
One problem is
this.queues = Array.from({length: numOfQueues}).fill([])
.fill
does not work well with non-primitives (usually), since each item in the new array will be a reference to the same object. You've only created a single array. The problem is the same as why the following doesn't work as one might expect:
const subarr = [];
arr.push(subarr);
arr.push(subarr);
since there's only one subarr
.
Use a mapper function with Array.from
to explicitly create a new array for each iteration:
this.queues = Array.from({length: numOfQueues}, () => []);
Also, to iterate over the iterator, use for..of
- either that, or remove the found item from the array when it's found (otherwise, every time it's called, it'll return the same item).
You can control the number of tickets to remove at once with for..of
by passing an argument to the generator and keeping track of the number of elements yielded:
class ticketQueues {
constructor(numOfQueues = 3) {
this.queues = Array.from({length: numOfQueues}, () => []);
}
addSev1(ticket) {
this.queues[0].push(ticket)
}
addSev2(ticket) {
this.queues[1].push(ticket)
}
addSev3(ticket) {
this.queues[2].push(ticket)
}
*getTicketsBySeverity(limit) {
let count = 0;
for(const queue of this.queues) {
while (queue.length) {
yield queue.shift();
count++;
if (count === limit) {
return null;
}
}
}
return null
}
}
const queues = new ticketQueues()
queues.addSev1({timestamp: Date(), name: 't1'})
queues.addSev1({timestamp: Date(), name: 't1-2'})
queues.addSev2({timestamp: Date(), name: 't2'})
queues.addSev3({timestamp: Date(), name: 't3'})
for (const ticket of queues.getTicketsBySeverity(3)) {
console.log(ticket);
}
console.log(queues.queues);
Upvotes: 4