1

I have run into quite an annoying issue with my Javascript code due to its synchronous nature, in short the problem is I need to dump a load of data into an array.

This array is then written directly into a JSON file.

function main(callback)  {
  myarrary = [] 

  //run some SQL query via stored procedure

  for (result in query) {

    myarray.push({

      //my data is entered here
    })
  }

  let data = JSON.stringify({myarray: somedata}, null, 4)
  fs.writeFileSync('testingjson.json', data)
  callback();
}
main(another_function)

My issue is that the data dump and callback are executed immediately, as such no data is transferred to the file and 'another_function` relies on data being there so that doesn't work either.

Therefore I need the dump to wait for the loop to finish appending myarray

I have also tried entering the dump and callback into my for loop however they execute on the first iteration.

Any help is appreciated!

EcSync
  • 842
  • 1
  • 6
  • 20
  • You should **not** write file in *sync* if you need callbacks? – Nishant May 23 '19 at 06:43
  • @Nishant please can you elaborate? – EcSync May 23 '19 at 06:44
  • Are you running `node`? – Nishant May 23 '19 at 06:45
  • @Nishant I am yes – EcSync May 23 '19 at 06:45
  • 1
    Try `fs.writeFile(filename, data[, options], callback)`. – Nishant May 23 '19 at 06:47
  • @Nishant that sounds more like what I am looking for – EcSync May 23 '19 at 06:55
  • Problem 1) This code should work fine, see if there are exceptions? Put a debugger and see if the data is getting written. 2) You can use `async` for this kind of thing, that is how it is done unless you only have one thing to do like in a simple script. – Nishant May 23 '19 at 06:58
  • 1
    @Nishant , data can be written to the file if it is inside of the loop, however this isn't a solution as the file is opened thousands of times and slows the script down. I will look into an `async` solution – EcSync May 23 '19 at 07:02
  • Your `run some SQL query via stored procedure` could also be asnyc and without know that, there's no knowing wether `myarrary` is an empty array (it could very well be looking at your code) or contains the data you expect! – 1565986223 May 23 '19 at 07:06
  • @1556089774 If i place the dump in my loop it will send all of the data - so data can be written to myarray, however this isnt practical as it opens and writes the json for every loop iteration. I want the data to be dumped in the json once `myarray` is complete – EcSync May 23 '19 at 07:10

2 Answers2

1

Functionally your current code looks fine, except that you should not call the function as callback unless it is an asynchronous function.

Callbacks are usually associated with asynchronous API's. It is useful if you want main(...) to return immediately so that you can just continue with something else. Since that is the default behavior, the API is

fs.writeFile(filename, data[, options], callback)

So to convert your program to async, you need:

fs = require("fs");

function main(callback)  {

    // Oops. Why is query executed synchronously?

    query = sqlSync() ;

    fs.writeFile('delete.json', "Data", callback);

}

main(() => console.log("Done"))

You can also convert SQL calls to async if your API's support that (since it is an I/O operation).

Once you are comfortable with normal callbacks, you can try using promise or async-await as mentioned here.

Nishant
  • 20,354
  • 18
  • 69
  • 101
  • 1
    This IS the solution maybe @EcSync accept it ? I got this in my email as unanswered question but there's nothing to add or improve as far as I can see ! – vortex May 29 '19 at 00:11
0

if you have two methods who are returning callbacks you can use Promise.all([]). Here in Promise.all() you can write your database calls or other functions which are resolving/rejecting anything. From there you can get them in res object.

Abu Bakar
  • 65
  • 1
  • 8