Search code examples
typescriptasync-awaitchild-processspawn

How can I make child_process.spawn return a Promise in my TypeScript module?


I'm trying to write a little module that uses child_process.spawn to clone a git repo and return a Promise but it fails on me. When I'm using spawnSync it works.

Here is the sync code that works.

import {spawnSync} from 'child_process';
export default async function clone(options: { url: string; path: string; }) {
  const url = options.url;
  const target = options.path;
  const args = ['clone', url, target];
  return spawnSync('git', args);
}

This is the async code that fails and returns undefined

import {spawn} from 'child_process';
export default async function clone(options: { url: string; path: string; }) {
  const url = options.url;
  const target = options.path;
  const args = ['clone', url, target];
  const process = spawn('git', args);
  process.on('close', function () {
    return new Promise(function (resolve, reject) {
      process.addListener('error', reject);
      process.addListener('exit', resolve);
    });
  });
}

I also tried:

process.on('close', function (code) {
   return code;
  });

or

process.on('close', function (code) {
   return Promise.resolve(code);
  });

and several other things like …on('exit', function(code){ return code })

Any suggestions how to do this?


Solution

  • You're close, you just need to return the promise from your clone function (which doesn't need to be async, since you need to explicitly create the promise). Also, you're hooking the error event at the wrong time (and via the wrong method as far as I can tell):

    import {spawn} from 'child_process';
    // *** Not async
    export default function clone(options: { url: string; path: string; }) {
      // *** Return the promise
      return new Promise(function (resolve, reject) {
        const url = options.url;
        const target = options.path;
        const args = ['clone', url, target];
        const process = spawn('git', args);
        process.on('close', function (code) { // Should probably be 'exit', not 'close'
          // *** Process completed
          resolve(code);
        });
        process.on('error', function (err) {
          // *** Process creation failed
          reject(err);
        });
      });
    }