0

I know that this question is many.But mine is a little hard. I'm new to fs and i wanna read a file from txt and send it to client when it gives me a GET request and when it gives me a POST request. Sending the request is completly fine as i checked and its using XMLHttpRequest.First of all here is my code :

var http = require('http');
var fs = require('fs');
http.createServer(function (req, res) {
  console.log("Recieved request : " + req.method);
  fs.readFileSync("chat.txt",(err,data) => {
    console.log("hello");
    if(req.body){
        console.log("Received message : " + req.body);
        var chats = data.split("\n");
        if(chats.length == 40){
            chats.shift();
        }
        chats.push(req.body);
        var results = "";
        for(var i in chats){
            if(i == chats.length - 1){
                results += chats[i];
            }
            else{
                results += chats[i] + "\n";
            }
        }
        fs.writeFileSync("chats.txt",results);
    }
    else{
        console.log(data);
        res.end(data.toString("utf8"));
    }
  });
}).listen(8080);

I think the problem is from the Sync and Async of readFile and writeFile and beside this problem, Can you say what is async await and promises very summarized and simple?

AlirezaBest
  • 103
  • 7
  • the things in readfileSync doesnt run...Like `console.log("hello")` – AlirezaBest Aug 05 '23 at 19:29
  • 5
    `readFileSync()` doesn't take a callback function, the file content is the return value. – Barmar Aug 05 '23 at 19:30
  • 1
    The callback function is used with `readFile()`, not `readFileSync()`. – Barmar Aug 05 '23 at 19:31
  • why its used with readFile and not used in readFileSync? – AlirezaBest Aug 05 '23 at 19:31
  • 1
    Since it's synchronous, there's no need to use a callback, it would just make it more complicated. – Barmar Aug 05 '23 at 19:32
  • can you define synchronous and asynchronous in an answer? – AlirezaBest Aug 05 '23 at 19:33
  • Asynchronous functions return immediately, before the operation completes. They either return a promise or take a callback function that will be executed when the operation completes. – Barmar Aug 05 '23 at 19:33
  • 2
    That's JavaScript basics. – Barmar Aug 05 '23 at 19:33
  • I searched many documentaries about this but your answer was very good – AlirezaBest Aug 05 '23 at 19:34
  • https://www.freecodecamp.org/news/synchronous-vs-asynchronous-in-javascript/ – Barmar Aug 05 '23 at 19:36
  • Just a heads up, if your making a HTTP server then you defiantly want to use `readFile` and NOT `readFileSync` unless `readFileSync` was used in a worker. If you can also learn about `async / await`, you could then use `fs/promises` and that will make your code much easier to understand. – Keith Aug 05 '23 at 19:41
  • Note that you're not doing ANY validation of what's in `req.body`. A rogue client could literally send you anything. You cannot trust what is in there. You must verify it's contents seem appropriate before using it. – jfriend00 Aug 06 '23 at 16:10

1 Answers1

2

Node.js' fs.readFileSync and fs.writeFileSync are not accepting callbacks - they are synchronous. Instead, they return the relevant value and throw errors.

You also need to specify the encoding in fs.readFileSync() to make it return a string.

Your code should look something like this:

var http = require('http');
var fs = require('fs');
http.createServer(function (req, res) {
  console.log("Recieved request : " + req.method);
  // Read the file as text with UTF8 encoding and save the read data to a variable
  let data;
  try {
    data = fs.readFileSync("chat.txt", 'utf8');
  } catch(err) {
    // When an error occurs while reading the file
    // Do something with the error and return
    // because we have no data
    return;
  }
  console.log("hello");
  if(req.body){
    console.log("Received message : " + req.body);
    var chats = data.split("\n");
    if(chats.length == 40){
      chats.shift();
    }
    chats.push(req.body);
    var results = "";
    for(var i in chats){
      if(i == chats.length - 1){
        results += chats[i];
      } else {
        results += chats[i] + "\n";
      }
    }
    try {
      fs.writeFileSync("chats.txt", results);
    } catch(err) {
      // If an error occurs while saving the file
      // Catch it here and do something
      return;
    }
  } else {
    console.log(data);
    res.end(data.toString("utf8"));
  }
}).listen(8080);

EDIT: Added try/catch statements to catch errors while reading/writing the file.

MfyDev
  • 439
  • 1
  • 12
  • 2
    You are missing `try/catch` to catch errors on `fs.readFileSync()` and `fs.writeFileSync()`. – jfriend00 Aug 06 '23 at 02:49
  • @jfriend00 Good point, edited. – MfyDev Aug 06 '23 at 08:30
  • 1
    I'm glad you added `try/catch`, but it might have been better with one try/catch around the whole block of code because there are other places this code could throw and you probably don't need two separate try/catch blocks. Also, the key aspect of handling an error in a request handler is you MUST send a response to the incoming http request (probably a 500 response if it's an unknown or unexpected error). – jfriend00 Aug 06 '23 at 16:08