Git Product home page Git Product logo

Comments (9)

maxfi avatar maxfi commented on May 18, 2024 7

I also thought the same as @aikar on my first skim of the docs that queue.onIdle would register a callback.

EventEmitter style API and do queue.on('idle', () => { });

This would be awesome! An example use case might be:

someEventEmitter.on('new-doc', (doc) => 
  queue.add(
    () => db.add(doc)
  )
) 

queue.on('start', log('starting'))
queue.on('added', log('added'))
queue.on('resolved', log('resolved'))
queue.on('empty', log('empty'))
queue.on('idle', log('idle'))
// => 
// idle

someEventEmitter.emit('new-doc', ({id: 1}))
// =>
// starting
// added {id: 1}
// empty
// resolved 'database-id-1'
// idle

from p-queue.

sindresorhus avatar sindresorhus commented on May 18, 2024 2

A promise is intended to only be resolved once, however this library is expecting to resolve them multiple times.

A promise is not intended to resolve once, it can only resolve once. That's irrelevant though as we're not requiring you to resolve a promise multiple times. We're returning a fresh promise each time you call the method. This is a common pattern.

from p-queue.

jordanbtucker avatar jordanbtucker commented on May 18, 2024 2

I disagree with the other sentiments here. It was obvious to me that onIdle and onEmpty return single use promises because I understand how promises work.

If you call onIdle, it will return a promise that will resolve when the queue is done. If you add more items to the queue after the promise resolves, then you need to get a new promise by calling onIdle again. It's really quite simple.

I can also see how making PQueue an EventEmitter with an on('idle') event could be useful too, however.

from p-queue.

aikar avatar aikar commented on May 18, 2024

This relates to e91d91b

That commit resolves the double resolve issue.

However, if you rather keep the promise style API, i would suggest making it clearer in the documentation that if you want to always know about idle, you need to re-register the onIdle/onEmpty handler again, that calling this only informs you of the next idle.

I know this is expected behavior to anyone who understands the details of promises, but there will be plenty of users of this API who do not know that, or people who in my case, thought maybe you were doing something really hacky to call the .then() supplied callback multiple times.

The documentation was not clear to me that the intent of the API was a one time fire.

But an event emitter style with queue.once("idle", () =>{}); would satisfy this same desire ("I only need to know about the next idle"), and queue.on("idle"); satisfies "I need to know about every idle"

So I still recommend migrating the API to use an emitter, and make .onIdle()/.onEmpty() be forwarders to .once()

from p-queue.

sindresorhus avatar sindresorhus commented on May 18, 2024

I went with promises initially so you can await them easily and I didn't see think of any use-case for needing an event emitter. And yes, we can document it better.


So I still recommend migrating the API to use an emitter

What is your use-case for this? I'm just curious.

from p-queue.

aikar avatar aikar commented on May 18, 2024

I'm currently running 2 priority queues, with different concurrency levels, one high one low.

Because browsers have a limit on how many requests, can be pending to a single domain, I put "really low priority" items into the low priority queue with a lower concurrency level, ensuring there is always open room for a high priority request to come in and start.

I'm trying to avoid the case where there are many slow requests running, using up all available connections, and a higher priority request comes in, but is blocked by the slow ones.

Anytime the high queue takes work, I pause the low queue (letting the overlap in concurrency shift from low to high in the event the high queue gets a lot of requests), and once the high queue goes idle, I resume the low queue.

using a single queue works fine for controlling priority, but nothing would stop 6 low priority tasks that take say 5s+ to execute, from holding the queue up, making the high priority task still have to wait.

So the double queue approach solved this issue for me.

Another case would be even for non request oriented tasks, say you have some background task/poller/monitor that should run anytime the queue is idle, and paused anytime the queue has work, having easy start/stop events makes it easy to react to the queue changing state and control the external operation.

For example, a web based game may want to pause some CPU heavy task while high priority work is occuring.

but for onIdle/onEmpty, I understand that intent and that's fine now that the above linked commit fixed the implementation bug, just would be good to document the intent of how that API is to be used, and suggesting an event emitter style for people who just want to know event style state changes.

from p-queue.

hummal avatar hummal commented on May 18, 2024

Had also an issue with the onIdle and onEmpty calls.
See my Testcase: https://repl.it/@RandomPxl/p-queue-Test

I would expect onIdle to be called every time my queue runs idle to know when things are done.
If I use start even with items added I immediatly get onIdle called and then never again. So I would add onIdle multiple times which would cause it to be called multiple times.

I dont know your use cases but I would not like to add onIdle/Empty more than once.

Iam also not sure about it but wouldnt it be more like:
onIdle == empty && idle
instead of
onIdle == idle

Reason is a queue is never idling when there are still items left in the queue. Even when they are not processing

from p-queue.

szmarczak avatar szmarczak commented on May 18, 2024

I propose queue.isIdle and queue.onIdle([callback])

from p-queue.

szmarczak avatar szmarczak commented on May 18, 2024

@maxfi It's not safe.

queue.on('idle', () => {
	queue.add(item);
	// it's not idle anymore
});

from p-queue.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.