-
Notifications
You must be signed in to change notification settings - Fork 30.1k
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
Add input
option to async child_process methods
#25231
Comments
Sorry @sindresorhus but I'm 👎 on this. I'm not sure what the official mindset of the Node core team is, but the way I've always treated Node core is a small wrapper around V8 (for javascript), libuv (for async I/O), and a subset of UNIX syscalls (shimmed on non-UNIX systems). Nothing more. I'd even argue some of the (admittedly helpful) built-ins such as That being said, the standard input/output streams are just that - streams. They are character descriptors that cannot be That's why the Further, With this proposed feature, two things are happening:
So if the API design makes sense for how things actually work at a low level, and if the new feature causes confusion for those that use the low level facilities provided by Plus, |
-1 I don't see the value over simply doing Having the input option for the synchronous methods makes sense for obvious reasons. |
@mscdex Any comments on:
|
@sindresorhus Not really, I don't use Promises. |
@Qix- Imagine if your thinking was applied to all Node modules. You'd have to make your own wrappers for literally everything. Also, many modules would have been gone completely.
Then throw an error. Problem solved :)
I see no confusion. For example, if you're trying to send 500MB over 100MB/s and you expect to get it all at once - it's obvious you'll get it in parts. That's how data transfer works.
I disagree. For example, the The main point is to make things easier. Of course you can do everything on your own, but the question is: why? If there's something we can improve then let's do it. |
Yes, and? That's how software works. You compose smaller pieces into bigger pieces.
Using errors to mask poor API design is hardly solving problems..
And using EOF is how streams work. I don't see your point here.
This doesn't make anything easier. This muddies the concept of stream vs. payload for the ease of a few use-cases that should be using wrappers anyway. Having all of your stdin payload ready and in memory to be transferred is an application decision that happens outside of node. The fact is, the way |
Well, if you love it then go assembly :D
And we are here for that particular reason - to discuss the possibilities.
When someone passes an
Please refer to your sentence:
then read my answer again.
I just want to note, if there weren't any small changes we still would be using Node 8. |
Speaking for myself only and not the project, but speaking as someone deeply involved for a few years: Node.js has always had tension between the ideals of "small core" and "batteries included". This has frustrated some folks who want one of those two ideals to be the only ideal. And there have certainly been some missteps where Node.js has included stuff that many of us later wish it hadn't and now we're stuck with. But overall, I believe the success of Node.js is owed largely to striking a reasonably good balance between the ideals. (For example, and my opinion only: "Small core" would have omitted the What this means is that ultimately we make decisions about what to include and what to omit on a case-by-case basis, making the best judgment we can at the time with the information we have. Personally, I'm still pondering this one. |
@Trott I don't see how this adds any functionality not originally in Node - nor does it really simplify an existing process. To me, it feels like it's based entirely out of confusion around the streaming API. It's not node's job to solve that. I don't see how this does anything more whatsoever. |
@Qix- even when I understand that there is some technical reason why it works as it is today. My only argument will be that we need to start moving the level of abstraction a little higher without losing the underline control. Because it is closer to how low-level works shouldn't be the reason why it works that way today, to be honest. But I also would prefer to keep Node as lean as possible, but this will require massive support from leaders and NodeJS foundation on directions and the creation of a good ecosystem then. Yes, many people are aware of I am 50%, 50% on this.
I think it is NodeJS or V8 to solve this, the whole point of creating such of languages and abstraction is to move to the next level of abstraction don't you think? |
@yordis you contradict yourself. Either you have abstractions such as this, or you have a "lean core". You can't have both. Secondly, wanting to kill off the concept of packages because you don't trust them isn't going to happen. Making node entirely batteries included would make it massive.
Not even a little bit, no. As I said in my first comment above, Node's point (as I see it) is to be a Javascript engine wrapping async unix system calls. Nothing more. |
Tell me more --->
I don't want that. Being mainly on Erlang/OTP and Elixir, I want these tools to be as lean as possible. OTP if I am not mistaking is starting to move things into packages so the core focus in does one thing really well. But the community of Erlang/Elixir support these type of movements, this is why we need to start shaping a little bit JavaScript community.
Fair enough, this is 50% of what I love, the other 50% is forced by the community, but no because pragmatically speaking I want it on NodeJS. |
I’m in favor of this one as long as it is implemented as child.stdin.end(input). In this way the input option and stdin could not be misused. |
@Qix- It is Node's job to provide a useful, intuitive, and reasonably powerful abstraction in its APIs, among which streams and child processes are important ones. Even if we take your viewpoint for granted, that this feature request is borne out of misunderstanding of the API, then this is an opportunity for the core team to learn. Why was it misunderstood by experienced Node.js users? That deserves some thought. The numbers here are also interesting. execa has 5.5 million downloads per week on npm. To me, this signals that the The possibility for misuse also seems overblown to me. The |
Because they haven't taken the time to learn how process I/O works at the system level. This isn't Node's fault.
This is confirmation bias. We do not have stats on how many people would have "downloaded" Conversely, node's API is very much similar to the
Because the sync APIs cannot function without it.
This doesn't make sense to me, could you explain? If the |
@Qix- Why those many people should care about how I/O works at a system level in 2019? If you are not working in low-level software that requires would require such of knowledge this is pretty much pointless and contra-productive. I see that you love to know how things work and you do not have issues with understanding low-level APIs. So I, I love as you do understanding how things work but pretending that everyone should be like us is selfish. I want people like you that enjoy these topics working on the core of NodeJS or V8, but for the rest of us, the best we could do is to focus in the next layer of abstraction. Win-win. If you are going to think that way, where people should know how everything works, well, we all should code in Assembly and be good at it. Right?! This topic is where I find myself hating the idea that NodeJS is merely a wrapper. I will stop here since this is just a philosophical/subjective topic and as I said, I am 50%/50% on adding these type of APIs to NodeJS itself instead of being on an external package as today. We are not a disciplined community to do so. |
I'm not going to respond to a reductio ad absurdum response such as that. No, obviously we shouldn't be writing pure assembly - that's a common argument people make in favor of needless abstraction. Talking down to me doesn't help further this conversation. I will add that it's the responsibility of all of us to understand our field and to keep complexity to a minimum. I don't think this addition brings us any closer to that. |
I think that it's too much abstraction. |
Hey 👋 I'm not too happy with how discussion went down here - I feel like the idea proposed by @sindresorhus was shot down very quickly without first discussing alternatives and options. I feel like valid and relevant technical points were raised but also some less constructive arguments. I'd love to see some constructive discussion on the pros and cons. Note that we can do other things for the promises version of const { execFile } = require('child_process').promises;
// later in an async function, we might have an API like:
const child = await execFile('node').stdin.end('foo');
// or something like:
const child = await execFile('node');
child.stdin.write('foo'); // added to ChildProcess object returned from promises
// or something like:
const child = execFile('node').stdin.write('foo');
await child.ready // child is returned synchronously, exposes a property for the promise Or anything we'd like really. |
But are we discussing an addition to the Promises API or an addition to the existing API? Those are two very different things. |
@qix I think the underlining problem is how execFile, etc API works with async/await. As an example, it's not possible to do: const cp = require('child_process');
const { promisify } = require('util');
const execFile = promisify(cp.execFile)
async function run () {
const { stdin, stdout, stderr } = await execFile('cat')
stdin.end('hello') // this will never be executed
return stdout
}); Overall I think |
What does const cp = require('child_process');
const { promisify } = require('util');
const execFile = promisify(cp.execFile);
async function run () {
const child = execFile('cat', {input: 'hello'});
child.stdin.end('world!');
const { stdout, stderr } = await child;
return stdout;
}); Hint: this script should throw an error. This is the confusion I'm talking about. |
In general, i don’t think a promise-based version of a callback-based api in node should have a different API - that makes it harder to refactor between the forms. If a change is worth making, it’d be worth making in both interfaces, imo. |
Nevermind, totally wrong, should have thought more, promise would have to be awaited to get I/O streamsI'm indifferent to whether the input option is added or not, but I don't think the promise argument is relevant. This is a common issue with `await` and promises that are tied to additional interaction, the solution in both cases is to use a different pattern:const cp = require('child_process');
const { promisify } = require('util');
const execFile = promisify(cp.execFile)
async function run () {
const sp = execFile('cat')
const { stdin, stdout, stderr } = sp
stdin.end('hello')
await sp
return stdout
} const cp = require('child_process');
const { promisify } = require('util');
const execFile = promisify(cp.execFile)
async function run () {
const sp = execFile('cat', {input: 'hello'})
const { stdin, stdout, stderr } = sp
stdin.end('world!')
await sp
return stdout
} Seems to me that the implementation would just call |
There has been no activity on this feature request for 5 months and it is unlikely to be implemented. It will be closed 6 months after the last non-automated comment. For more information on how the project manages feature requests, please consult the feature request management document. |
unstale |
There has been no activity on this feature request for 5 months and it is unlikely to be implemented. It will be closed 6 months after the last non-automated comment. For more information on how the project manages feature requests, please consult the feature request management document. |
There has been no activity on this feature request and it is being closed. If you feel closing this issue is not the right thing to do, please leave a comment. For more information on how the project manages feature requests, please consult the feature request management document. |
This is still a desired feature. Can someone please reopen? |
There has been no activity on this feature request for 5 months and it is unlikely to be implemented. It will be closed 6 months after the last non-automated comment. For more information on how the project manages feature requests, please consult the feature request management document. |
Please keep this open. |
I'm putting this out to pasture. It's been open for over 4 years and there's no consensus (mild understatement) on whether it's a desirable feature, let alone what the details should look like. |
input option added to spawn, exec and execFile. tests and documentation updated Fixes: nodejs#45306 Fixes: nodejs#25231
Is your feature request related to a problem? Please describe.
When spawning a child process, it's common to want to send some data to the process' stdin. Usually, a string or buffer. This can be done by writing to the stdin stream:
However, that's a bit verbose and not that obvious. It's also easy to forget to call
.end()
, see #2339.Describe the solution you'd like
I propose the async
child_process
methods get aninput
option for convenience. Just like the synchronous methods already have.This will also improve the stdin situation when a
child_process
method is promisified, as it then returns aPromise<Object>
withstdout
andstdin
instead of theChildProcess
object.Describe alternatives you've considered
I could create a
child_process
wrapper that does this, however, I have already done that: https://github.com/sindresorhus/execa#input But I would like to upstream some of the most useful ideas from that package.// @floatdrop @Qix-
The text was updated successfully, but these errors were encountered: