Home > other >  Reading and sending data to user in sequence in node.js
Reading and sending data to user in sequence in node.js

Time:10-16

I'm coding website in node.js using express and socket.io. The server is sending to user photo and data from every file in directory using socket.emit function.

The problem with this code: The server is sending data from 2 files but image in second emit is same as first beacouse before sends first img is changing data of first file to second data.

I found this solution but it's not working. Some of the server side code:

function send(file) {

        return new Promise((resolve, reject) => {
                fs.readFile(dir   file, 'utf8', (err, jsonString) => {

                    jsonString = JSON.parse(jsonString);

                    buffer = ""
                    img = false

                    img_path = dir   jsonString.number

                    if (fs.existsSync(img_path   '.jpg')) {

                        fs.readFile(img_path   '.jpg', function (err, buf) {
                            buffer = buf
                            img = true
                        });
                    }
                    if (fs.existsSync(img_path   '.png')) {

                        fs.readFile(img_path   '.png', function (err, buf) {
                            buffer = buf
                            img = true
                        });
                    }

                    setTimeout(() => { // <---- Without wait buffer will be blank

                        console.log(img_path) //both times is same
                        data = {
                            number: jsonString.number,
                            image: img,
                            buffer: buffer.toString('base64')
                        }

                        socket.emit('data', data)
                        console.log("sended!")
                        resolve()
                    }, 100)

                    if (err) {
                        console.error(err);
                        return;
                    }
                });
    })
}

async function files() {

  fs.readdir(dir, (err, files) => {
      if (err) {
          throw err
      }

      files.forEach(async file => {
      
          if (file.split('.').pop() == 'json') {
             await send(file)
          }
       })
   })
}

files()

But this is not working. Thanks for help!

CodePudding user response:

There are a few misconceptions that have to addressed:

  • async and sync flows used in same context, that's why you needed a setTimeout
  • async function in forEach doesn't do what you expect
  • variable management, use let or const

Some small things:

  • argument passing, dir wasn't available in some contexts
  • async function definition for send

For example your code could be rewritten like this:
Do note that I did not run this program

const { promisify } = require("util");
const readFile = promisify(fs.readFile);
const exists = promisify(fs.exists);
const readdir = promisify(fs.readdir);

async function getBuffer(filePath) {
  const isFile = await exists(filePath);
  if (!isFile) return;
  return readFile(filePath);
}

async function send(dir, file) {
  const content = await readFile(file, 'utf8');

  if (!content) return;

  const json = JSON.parse(content);
  const img_path = dir   json.number;

  const buf1 = await getBuffer(`${img_path}.jpg`);
  const buf2 = await getBuffer(`${img_path}.png`);

  console.log(img_path);
  const data = {
    number: json.number,
    image: buf1 || buf2,
    buffer: (buf1 || buf2).toString('base64'),
  }
  socket.emit('data', data);
  console.log("sended!");
}

async function files(dir) {
  const files = await readdir(dir);
  for (const file in files) {
    if (file.split('.').pop() === 'json') {
      await send(dir, file);
    }
  }
}

files("<directory>");
  • Related