promisify-node icon indicating copy to clipboard operation
promisify-node copied to clipboard

Problem with fs.writeFile

Open sstur opened this issue 9 years ago • 4 comments

This appears to be caused by the fact that fs module is mutated by promisify('fs'). Internally, fs.writeFile uses some other fs methods in a callback fashion, so it expects fs to be un-modified.

Repro:

const promisify = require('promisify-node');
const fs = promisify('fs');
fs.writeFile('./testfile.txt', 'Hello World')
  .then(() => {
    console.log('File saved!');
  })
  .catch((error) => {
    console.error('Error doing something:', error);
  });

Neither 'File saved!' or 'Error doing something' ever gets logged. The file gets created but no data is written to it. Tested on OS X 10.11 using Node v5.

sstur avatar Feb 09 '16 23:02 sstur

Just hit this too. Tested on Ubuntu 14.04 using Node v5. Pretty unfortunate :(

thedillonb avatar Feb 28 '16 23:02 thedillonb

Actually, to add to this, because it mutates the module then all other files that require this module are affected. This cause cause some serious havoc if not rectified. For example, by promisifying fs it essentially breaks express since it internally uses fs to serve static content.

thedillonb avatar Feb 29 '16 00:02 thedillonb

I get this too:

ohnobinki@gibby ~/require-semver $ node -e 'require("fs").writeFile("a", "b\n", () => console.log("done"))'; cat a
done
b
ohnobinki@gibby ~/require-semver $ node -e 'require("promisify-node")(require("fs")).writeFile("a", "b\n").then(() => console.log("done"))'; cat a
ohnobinki@gibby ~/require-semver $ 

binki avatar Aug 14 '16 04:08 binki

Interestingly, if I don’t invoke require('fs') myself but let promisify-node do that for me, it works as expected:

ohnobinki@gibby ~/require-semver $ node -e 'require("promisify-node")("fs").writeFile("a", "b\n").then(() => console.log("done"))'; cat a
done
b

So there’s at least a workaround. I have no idea why it’s behaving this way. I tried adding to promisify-node’s testsuite and couldn’t reproduce the behavior inside the testsuite, even when supposedly deleting 'fs' from require.cache and using promisify(require('fs')) rather than promisify('fs').

Oh, but it looks like when you pass a string and have promisify() call require() for you, it automatically behaves as if you specified noMutate as true. And somehow specifying noMutate works around this bug. So this also works:

ohnobinki@gibby ~/require-semver $ node -e 'require("promisify-node")(require("fs"), undefined, true).writeFile("a", "b\n").then(() => console.log("done"))'; cat a
done
b

binki avatar Aug 14 '16 05:08 binki