Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrapping everything in nextTick() should be optional #29

Closed
indutny opened this issue Nov 16, 2011 · 4 comments
Closed

Wrapping everything in nextTick() should be optional #29

indutny opened this issue Nov 16, 2011 · 4 comments

Comments

@indutny
Copy link

indutny commented Nov 16, 2011

Calling nextTick is good for letting other parts of application to execute, but it may cause nonobvious problems when dealing with streams in node.js.

For example, creating ReadStream and then using it after resolve will end up in skipping some "data" events on it, because we skipped one event-loop tick.

@kriskowal
Copy link
Owner

The purpose of calling nextTick in this case is not so much to permit interleaving, but to force deterministic interleaving of the callbacks. Callbacks are required to occur in future turns, instead of occurring either on the stack or in a future turn. Using nextTick increases the robustness of everything built on top of Q.

It’s relatively straightforward to safely handle a readable stream in conjunction with promises.

https://github.com/kriskowal/q-io/blob/master/q-io.js#L13-100

(Needs further work to support throttling, but has been indispensable for my stack.)

@indutny
Copy link
Author

indutny commented Nov 17, 2011

Yes, running callbacks on stack is not preferable for flow control module, I agreed.

But can you please point me to any place where such nextTick behaviour is documented? I spent some time on figuring out, why streams was broken in my app, and it'll be great to let everyone know that callbacks are running not immediately.

@kriskowal
Copy link
Owner

Thanks. The documentation needs another pass for clarity, for sure. nextTick reads as “called in a future turn of the event loop” throughout README.md

excerpt:

when(value, fulfilled_opt, rejected_opt)

Arranges for fulfilled to be called:

  • with the value as its sole argument
  • in a future turn of the event loop
  • if and when the value is or becomes a fully resolved

Arranges for rejected to be called:

  • with a value respresenting the reason why the object will
    never be resolved, typically an Error object.
  • in a future turn of the event loop
  • if the value is a promise and
  • if and when the promise is rejected

Returns a promise:

  • that will resolve to the value returned by either of the
    callbacks, if either of those functions are called, or
  • that will be rejected if the value is rejected and no
    rejected callback is provided, thus forwarding
    rejections by default.

The value may be truly any value. It can be a function.
It can be a promise.

Either callback may be falsy, in which case it will not be
called.

Guarantees:

  • fulfilled will not be called before when returns.
  • rejected will not be called before when returns.
  • fulfilled will not be called more than once.
  • rejected will not be called more than once.
  • If fulfilled is called, rejected will never be called.
  • If rejected is called, fulfilled will never be called.
  • If a promise is never resolved, neither callback will
    ever be called.

@kriskowal
Copy link
Owner

Now tracking as #31.

domenic added a commit that referenced this issue Apr 21, 2012
Also added a special note about streams.

Closes #31, with special consideration for the concerns of #29.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants