Home > front end >  Node: How keep old objects and push new data into file Json
Node: How keep old objects and push new data into file Json

Time:08-13

i want to fetch the old values from file Json if my script turns off from work and then insert the new values into the json file. i read the file and then converted the JSON file the code works safely, but i have a problem that it prints for me once

const dataFile = fs.readFileSync('data.json', 'utf8')
let decodeJson = await JSON.parse(dataFile);
  decodeJson.table.push({name: 'test'})

this line is inside forEach loop so it is supposed to print 25 lines for each word test cuz after i want to write it in the same file data.json this line for forEach

getData.data.forEach(async details => {
  let currentPage = details.title;
  const dataFile = fs.readFileSync('data.json', 'utf8')
  if (dataFile === '') { // check if file json empty
    try {
      obj.table.push({
        name: details.title
      })
      let encodeJson = await JSON.stringify(obj);
      fs.writeFileSync("data.json", encodeJson)
      console.log('file is empty')
    } catch (err) {
      console.log(err);
    }
  } else {
    //read data with JSON from file
    try {
      let decodeJson = await JSON.parse(dataFile);
      // i want here keep old values   push new values (details.title)
      decodeJson.table.push({
        name: 'test'
      })
      //fs.writeFileSync('data.json', JSON.stringify(decodeJson))
    } catch (err) {
      console.log(err);
    }
  }
})

i tried some attempts but i failed and it still print me only one object...why?

let data = []
data.push('test')
decodeJson.table.push(data)

this is the result i got in consolelog

  table: [
    { name: 'Kimi ga Nozomu Eien' },
    { name: 'Kita e.: Diamond Dust Drops' },
    { name: 'Loveless' },
    { name: 'Blood ' },
    { name: 'Re: Cutey Honey' },
    { name: 'Solty Rei' },
    { name: 'Juuni Kokuki' },
    { name: 'Shaman King' },
    { name: 'X/1999' },
    { name: 'X' },
    { name: 'Mahou Sensei Negima!' },
    { name: 'Maria-sama ga Miteru' },
    { name: 'Boukyaku no Senritsu' },
    { name: 'Ima, Soko ni Iru Boku' },
    { name: 'Peace Maker Kurogane' },
    { name: 'Pita Ten' },
    { name: 'Power Stone' },
    { name: 'Mononoke Hime' },
    { name: 'RahXephon' },
    { name: 'Samurai 7' },
    { name: 'Scrapped Princess' },
    { name: 's.CRY.ed' },
    { name: 'Shingetsutan Tsukihime' },
    { name: 'Slam Dunk' },
    { name: 'Strange Dawn' },
    [ 'test' ]
  ]
}

also my goal that i want to do is if script stopped and start back work. it returns back the old object that was stored in the Json file keeps adding a new object from the API i'm still a newbie and learning json so please treat me kindly

CodePudding user response:

forEach loops are synchronous

As already commented, neither JSON.parse nor JSON.stringify is asynchronous, so you don't need to use await for them.

Using await is causing the problem: array.prototype.forEach treats its argument as a synchronous function and discards any value returned from it. Effectively this means any promises returned from an async function provided are discarded without waiting for the promise to be settled.

Also async function executing an await operator synchronously return a promise the first time an await operator is executed within them.

Hence if data.json is empty, the await in

let encodeJson = await JSON.stringify(obj);

returns a promise before creating data.json content, which is sufficient for the forEach loop to continue. All remaining iterations will do the same and when resumed will overwrite the data.json file created in the previous iteration. However, since each iteration updated an outer variable obj, the last version of data.json should be correct.

Similar conditions apply to an existing data file however: each loop iteration reads the existing file and returns a promise when

await JSON.parse(dataFile);

is executed, allowing the next iteration to proceed and read the same input data and overwrite the file written by the previous iteration.

Major lessons are to not use forEach for asynchronous work that needs to complete within a single iteration, and not to use await in code that must execute synchronously.

In this particular case, leaving out the await operators, staying with synchronous writes, and removing async before the loop function declaration should be sufficient to solve the issue. A better solution may be to read data.json once before starting the loop, and write it once after finishing the loop.

  • Related