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.