0

Trying to understand the appropriate way to implement async/await in an async function being called from another function.

  public async checkTargetPath(path: string) {
    const nixPath = upath.toUnix(path);
    let isDir;
    let isFile;
    const dirTest = await fls.stat(nixPath, (err, stats) => {
      if (err) {
        throw new Error(`${err.message}`);
      } else {
       return isDir = stats.isDirectory();
      }
    });
    const fileTest = await fls.lstat(nixPath, (err, stats) => {
      if (err) {
        throw new Error(`${err.message}`);
      } else {
        return isFile = stats.isFile();
      }
    });
    if (isDir === true) {
      return nixPath;
    } else {
      return null;
    }
  }

Which is called from here:

  public async copyXmlFromPath(path: string) {
    const pathHasTrailingSlash = path.endsWith('/');
    if (pathHasTrailingSlash === false) {
      path = path + '/';
    }
    const exec = util.promisify(require('child_process').exec);
    const { stdout, stderr } = await exec(`cp ${path}package.xml ./`);

    if (stderr !== '') {
            throw new Error(`${stderr}`);
    } else if (stdout !== '') {
      console.log(`package.xml was copied from ${path} to ./`);
    }
  }

When I step through it, the values of isDir and isFile from the first function are always undefined, which I think is because the promises are not resolved.

Can someone point out the failures in the implementation and suggest how to resolve :) ? Links welcome if there are examples that aren't just code blocks!

trebleCode
  • 2,134
  • 19
  • 34
  • What are `fls.stat` and `fls.lstat`? Is `fls` the `fs` module? (Typically you'd call it `fs` to avoid this kind of ambiguity.) The way you're calling it is a bit double-minded: You're `await`ing it as though it returned a promise, but you're also passing it a Node.js callback. Typically you do one **or** the other depending on the function you're calling. – T.J. Crowder Oct 03 '19 at 15:02
  • My bad, Yes, `fls` is the imported `fs` module. Another module I'm using already imports the name `fs` by default for something else. @T.J.Crowder In this case I just want to copy a file from one location to another, and trying to better understand `async/await` in node. Is one approach more appropriate than the other here, or just pick one and stay consistent with it? – trebleCode Oct 03 '19 at 15:03
  • I believe `await fls.stat(nixPath, (err, stats) => ... )` is inherently wrong, because you await a function _and_ you pass it a callback. You can't have both. You either await a function _or_ pass it a callback, you are mixing up two different ways of programming. The very goal of the `async/await` is to not use callback functions. – Jeremy Thille Oct 03 '19 at 15:05
  • Thanks for the quick reply, will give the other post a read. – trebleCode Oct 03 '19 at 15:07
  • @trebleCode - Node.js's `fs` module functions doesn't provide promises; there is a [`promises` version of it](https://nodejs.org/api/fs.html#fs_fs_promises_api) that does. You might want to use that. But you're also using `exec` with `await` which also assumes that `exec` returns a promise (it doesn't). See the linked question for how to use Node.js-callback-style API functions with promises. (Promises are the underlying plumbing for `async` functions.) – T.J. Crowder Oct 03 '19 at 15:14

0 Answers0