Giter Site home page Giter Site logo

promisify-child-process's Introduction

promisify-child-process

CircleCI Coverage Status semantic-release Commitizen friendly npm version

seriously like the best async child process library

Based upon child-process-async, but more thorough, because that package doesn't seem very actively maintained.

promisify-child-process provides a drop-in replacement for the original child_process functions, not just duplicate methods that return a Promise. So when you call exec(...) we still return a ChildProcess instance, just with .then(), .catch(), and .finally() added to make it promise-friendly.

Install and Set-up

npm install --save promisify-child-process

If you are using a old version of Node without built-in Promises or Object.create, you will need to use polyfills (e.g. @babel/polyfill).

// OLD:
const { exec, spawn, fork, execFile } = require('child_process')
// NEW:
const { exec, spawn, fork, execFile } = require('promisify-child-process')

Upgrading to v3

You must now pass maxBuffer or encoding to spawn/fork if you want to capture stdout or stderr.

Resolution/Rejection

The child process promise will only resolve if the process exits with a code of 0. If it exits with any other code, is killed by a signal, or emits an 'error' event, the promise will reject.

Capturing output

exec and execFile capture stdout and stderr by default. But spawn and fork don't capture stdout and stderr unless you pass an encoding or maxBuffer option:

const { spawn } = require('promisify-child-process');

async function() {
  // captures output
  const { stdout, stderr } = await spawn('ls', [ '-al' ], {encoding: 'utf8'});
  const { stdout, stderr } = await spawn('ls', [ '-al' ], {maxBuffer: 200 * 1024});

  // BUG, DOESN'T CAPTURE OUTPUT:
  const { stdout, stderr } = await spawn('ls', [ '-al' ]);
}

Additional properties on rejection errors

If the child process promise rejects, the error may have the following additional properties:

  • code - the process' exit code (if it exited)
  • signal - the signal the process was killed with (if it was killed)
  • stdout - the captured stdout (if output capturing was enabled)
  • stderr - the captured stderr (if output capturing was enabled)

Wrapper

If for any reason you need to wrap a ChildProcess you didn't create, you can use the exported promisifyChildProcess function:

const { promisifyChildProcess } = require('promisify-child-process');

async function() {
  const { stdout, stderr } = await promisifyChildProcess(
    some3rdPartyFunctionThatReturnsChildProcess(),
    { encoding: 'utf8' }
  )
}

Examples

exec()

async function() {
  const { stdout, stderr } = await exec('ls -al');
  // OR:
  const child = exec('ls -al', {});
  // do whatever you want with `child` here - it's a ChildProcess instance just
  // with promise-friendly `.then()` & `.catch()` functions added to it!
  child.stdin.write(...);
  child.stdout.pipe(...);
  child.stderr.on('data', (data) => ...);
  const { stdout, stderr } = await child;
}

spawn()

async function() {
  const { stdout, stderr, code } = await spawn('ls', [ '-al' ], {encoding: 'utf8'});
  // OR:
  const child = spawn('ls', [ '-al' ], {});
  // do whatever you want with `child` here - it's a ChildProcess instance just
  // with promise-friendly `.then()` & `.catch()` functions added to it!
  child.stdin.write(...);
  child.stdout.pipe(...);
  child.stderr.on('data', (data) => ...);
  const { stdout, stderr, code } = await child;
}

promisify-child-process's People

Contributors

conr2d avatar douglascayers avatar greenkeeper[bot] avatar hwinkler avatar jedwards1211 avatar jrmclaurin avatar renovate-bot avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

promisify-child-process's Issues

`child.stdout` not available after `spawn`

In this example, child.stdout is null for me.

async function() {
  const { stdout, stderr, code } = await spawn('ls', [ '-al' ], {encoding: 'utf8'});
  // OR:
  const child = spawn('ls', [ '-al' ], {});
  // do whatever you want with `child` here - it's a ChildProcess instance just
  // with promise-friendly `.then()` & `.catch()` functions added to it!
  child.stdin.write(...);
  child.stdout.pipe(...);
  child.stderr.on('data', (data) => ...);
  const { stdout, stderr, code } = await child;
}

Time consuming process waits indefinitely

Hi,

It seems that time consuming process wait indefinitely in this package.

I ended up using exec which seems to work fine for time consuming process.

In case you would like to look more into this, please let me know, I will add more details in here, on how to reproduce this bug.

Steps to reproduce:

Prerequisite:

  1. Install ffmpeg, if you don't already have one
  • Windows:
    choco install ffmpeg
  • Ubutnu:
sudo apt update
sudo apt install ffmpeg

Steps:

  1. Unzip this

  2. Run workingcode.js
    node workingcode.js
    It works fine, takes around 15mins to generate

  3. Run buggycode.js
    node buggycode.js
    It waits indefinitely, you can confirm by observing the cpu usage

Now try reducing the repeat variable to 10 in buggycode.js and re run the code, and it will work just fine.

  1. To run the process from command prompt:
    ffmpeg -stream_loop 170 -i "video.mp4" -i "audio.mp3" -vf "subtitles=subtitle.srt:force_style='Alignment=2,OutlineColour=&H100000000,BorderStyle=3,Outline=1,Shadow=0,Fontsize=18,MarginL=0,MarginV=60'" -crf 24 -vcodec libx264 -preset ultrafast -map 0:v -map 1:a -c:a copy -shortest "output.mp4"

Thanks

Don't capture console output by default in spawn (breaking change)

Part of the behavior I copied over from child-process-async is automatically capturing the console output from a spawn()ed process, to resolve the promise with.

But, since the output is all buffered to memory there's a huge danger that it will run out of memory (and I think I've seen it do just that on long-running webpack-dev-server processes...)

This is why exec has a maxBuffer option (if the output buffer exceeds this size it will error out). We could add this option to spawn in this package, though unfortunately it would make this package less consistent with the node API, so I need to think about it for awhile longer.

Option to not throw on non-zero exit code

It seems to throw on non-zero exit code. I would like to avoid wrapping in try/catch, and read the code.

The documentation has an example showing usage of the {code} in the result. This is confusing because you cannot read the code it if throws.

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this πŸ’ͺ.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here is some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


Invalid npm token.

The npm token configured in the NPM_TOKEN environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/.

If you are using Two-Factor Authentication, make configure the auth-only level is supported. semantic-release cannot publish with the default auth-and-writes level.

Please make sure to set the NPM_TOKEN environment variable in your CI with the exact value of the npm token.


Good luck with your project ✨

Your semantic-release bot πŸ“¦πŸš€

How to get rejected promise instead of output.stderr

@jedwards1211 ,

This is more like a question/suggestion than issue.

Currently, the library returns an object with {stderr: string| undefined, stdout: string|undefined}. I think it would make more sense, since it is promise based, if it returns a rejected promise instead of stderr. That way, the consumer does not have to look for stderr specifically but they can use a catch block instead and get a single string in stdout instead of object. I think that would simplify a lot of code and would improve readability.

So question is, was there there any specific reason it is not implemented? Can this be taken under consideration and implemented?

Also this section says, it will return rejected promise in case of error which I think is misleading/confusing.

Example for fork

Hallo, can somesome provide me with an example for fork() since I somehow can not sending data from parent to child process with send().

When I tried (this is basically the send() example from node.js doc):

parent.js

import { fork } from 'promisify-child-process'

const child = fork('child.js', {
    encoding: 'utf8',
  })

child.send({ hello: 'world' })

// Causes the child to print: CHILD got message: { hello: 'world' }
child.on('message', (m) => {
  console.log('PARENT got message:', m);
});

await child

child.js

process.on('message', (m) => {
  console.log('CHILD got message:', m);
});

// Causes the parent to print: PARENT got message: { foo: 'bar', baz: null }
process.send({ foo: 'bar', baz: NaN });

process.exit()

I only get in the console:

PARENT got message { foo: 'bar', baz: null }

but no 'CHILD got message...' log.

Dependency deprecation warning: travis-deploy-once (npm)

On registry https://registry.npmjs.org/, the "latest" version (v5.0.11) of dependency travis-deploy-once has the following deprecation notice:

We recommend to use Travis Build Stages instead

Marking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake.

Affected package file(s): package.json

If you don't care about this, you can close this issue and not be warned about travis-deploy-once's deprecation again. If you would like to completely disable all future deprecation warnings then add the following to your config:

"suppressNotifications": ["deprecationWarningIssues"]

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: Preset name not found within published preset config (monorepo:angularmaterial). Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

[typescript] PromisifyChildProcessOptions missing properties

PromisifyChildProcessOptions in the typescript definition index.d.ts is missing maxBuffer and killSignal properties that are available for PromisifyChildProcessBaseOpts in index.js.

For example,

// src/index.js
type PromisifyChildProcessBaseOpts = {
  encoding?: $PropertyType<child_process$spawnSyncOpts, 'encoding'>,
  killSignal?: $PropertyType<child_process$spawnSyncOpts, 'killSignal'>,
  maxBuffer?: $PropertyType<child_process$spawnSyncOpts, 'maxBuffer'>,
}

differs from the definition file:

// index.d.ts
interface PromisifyChildProcessOptions {
  encoding?: string
}

In practice, this leads to typescript compile errors in the following syntax when trying to specify either maxBuffer or killSignal in the options to spawn.

import * as childProcess from 'promisify-child-process';

childProcess.spawn(cmd, args, {
    maxBuffer: 5 * 1024, // Error: Argument of type '{ maxBuffer: number; }' is not assignable to parameter of type 'PromisifySpawnOptions'
});

Expected Behavior

That killSignal and maxBuffer are part of the index.d.ts typescript definition as it appears from the source code for function promisifyChildProcess that they are supported options.

Thanks

Unnecessarily large install size

There are redundant files being published that significantly bloat the install size, which is currently 508 kB:

This is a shame because the actual code is quite elegant at ~5 kB:

https://unpkg.com/browse/[email protected]/index.js

Notably the 356 kB yarn.lock file should not be published.

It is best practice to whitelist exactly what should be published via a package.json files field, instead of using a blacklist via .npmignore:

https://github.com/jcoreio/promisify-child-process/blob/v3.1.4/.npmignore

Another opportunity to reduce the install size a bit is to remove dev tool config from the package.json out into separate config files, which will not be published due to the
package.json files field whitelist.

A little more tricky, but it would be nice to get rid of the Babel runtime dependency, as it appears to only be used for the CJS interopRequireDefault helper yet it pulls in the regenerator-runtime dependency:

https://unpkg.com/browse/[email protected]/index.js

Screen Shot 2020-05-05 at 12 31 32 pm

I suggest refactoring the source to CJS, and using an ESM wrapper with a package.json exports field with conditional exports:

https://nodejs.org/api/esm.html#esm_approach_1_use_an_es_module_wrapper

Then you won't need Babel, and Node.js ESM will be supported whilst avoiding the dual package hazard.

revisit close vs. exit

I think I need to only resolve on close, the spawnSync docs say:

The child_process.spawnSync() method is generally identical to child_process.spawn() with the exception that the function will not return until the child process has fully closed.

Missing typescript definition file in v3.1.2

After updating from v3.1.1 to v3.1.2, compiler is complaining with below error:

Could not find a declaration file for module 'promisify-child-process'. '/Users/pratik/dev/code/utilities/node_modules/promisify-child-process/index.js' implicitly has an 'any' type.
  Try `npm install @types/promisify-child-process` if it exists or add a new declaration (.d.ts) file containing `declare module 'promisify-child-process';`

5 import { exec } from 'promisify-child-process';
                       ~~~~~~~~~~~~~~~~~~~~~~~~~

For now, I have reverted back to 3.1.1 specifically but it would be helpful if it is fixed in the upstream.

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.