javascriptnode.jsreadfilewritefilenode.js-fs

Node.js: should reject with an error if the passed data is invalid


I'm getting a problem while running the test cases using the node.js application where I'm creating a directory if not exists, writing the json and reading the file.

Here's the Working Demo Link

It's throwing the below error even after handling the error in the code. I didn't get much help from other solutions related to Promise rejection in Stackoverflow. Looking for a working solution. I'm getting the below issue after doing npm test:

should reject with an error if the passed data is invalid:

Uncaught TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Promise
  at TypeError.get (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:35:385021)
  at EventEmitter.emit (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:35:143926)
  at process.onGlobalUncaughtException [as _fatalException] (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:35:363886)
  at triggerUncaughtException (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:42:367400)
  at processPromiseRejections (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:35:1794051)
  at processTicksAndRejections (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:35:801887)
  at _0x263935 (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:37:263515)

While doing npm start I'm getting the below problem:

Server running at http://127.0.0.1:3000/
Error: Invalid data
    at writeJSON (file:///home/projects/stackblitz-starters-xzxhal/index.js:70:15)
    at Server.eval (file:///home/projects/stackblitz-starters-xzxhal/index.js:24:15)
TypeError [ERR_INVALID_ARG_TYPE]: The "chunk" argument must be of type string or an instance of Buffer or Uint8Array. Received an instance of Promise
    at TypeError.get (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:35:385021)
    at triggerUncaughtException (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:42:367449)
    at processPromiseRejections (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:35:1794051)
    at processTicksAndRejections (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:35:801887)
    at _0x263935 (https://stackblitzstartersxzxhal-cstc.w-credentialless.staticblitz.com/blitz.a19575a2.js:37:263515) {
  code: 'ERR_INVALID_ARG_TYPE'
}

Here's my index.js file code pieces:

const server = http.createServer(async (req, res) => {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    const dirPath = DIR_PATH + dirs[0];
    const filePath = dirPath + './data.json';
    let createdDirectoryIfNotExists = await createDirectoryIfNotExists(filePath);
    if (createdDirectoryIfNotExists) {
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.write(writeJSON('./temp', contents));
        res.end();
    }
});

// write json in file
const writeJSON = async (filePath, contents) => {
    try {
        if (contents && typeof contents === "object") {
            const jsonString = JSON.stringify(contents);
            // write file 
            let isWriteFileSynced = fs.writeFileSync(filePath, jsonString, error => {
                if (error) {
                    console.log(error);
                } else {
                    return jsonString;
                }
            })
            if (isWriteFileSynced) {
                // read file after file is written
                let isReadFileSynced = fs.readFileSync(filePath, "utf8", (error, jsonString) => {
                    if (error) {
                        return false;
                    } else {
                        return jsonString;
                    }
                })

                // if read file, return the jsonString
                if (isReadFileSynced) {
                    return jsonString;
                }
            } else {
                throw new Error("Invalid data");
            }
            return jsonString;
        }
    } catch (error) {
        console.log(error);
        return;
    }

};


// create directory if not exists
const createDirectoryIfNotExists = async (path) => {
    fs.mkdirSync(path, { recursive: true });
    return true;
};

How to solve this issue?


Solution

  • That error comes from writeJSON, which returns unresolved Promise, hence the error

    So, you need to await it:

    res.write(await writeJSON('./temp', contents));
    

    But, as pointed out in the comments, you use sync methods within the function, so no need to return a Promise, so no need to use async on writeJSON function

    Also, fs.writeFileSync does not take a callback, and it returns undefined, so the check part will always fail.

    It throws, so you need to wrap both fs methods in try/catch, and return json from the try part.

    Also, not sure why you read the file afterwards, if it didn't throw, it's written but you can reorganize that:

    Here's a starter that should work (somewhat):

    const writeJSON = (filePath, contents) => {
      try {
        if (contents && typeof contents === 'object') {
    
          const jsonString = JSON.stringify(contents);
    
          // write file
          try {
    
            fs.writeFileSync(
              filePath,
              jsonString
            );
    
    
            // read file after file is written
            let isReadFileSynced = fs.readFileSync(
              filePath,
              'utf8'
    
            );
    
    
            // if read file, return the jsonString
            if (isReadFileSynced) {
              return jsonString;
            }
    
          } catch (err) {
            console.log(err);
          }
    
    
        } else {
          throw new Error('Invalid data');
        }
    
      } catch (error) {
        console.log(error);
        return;
      }
    };
    

    edit

    tests passing function:

    const writeJSON = async (filePath, contents) => {
     
        if (contents && typeof contents === 'object') {
          const jsonString = JSON.stringify(contents);
    
          // write file
          try {
            fs.writeFileSync(filePath, jsonString);
    
            // read file after file is written
            let isReadFileSynced = fs.readFileSync(filePath, 'utf8');
    
            // if read file, return the jsonString
            if (isReadFileSynced) {
              return jsonString;
            }
          } catch (err) {
            console.log(err);
            // todo
            throw new Error('err writing');
          }
        } else {
          throw new Error('Invalid Data');
        }
    
    };