1

I'm trying to iterate through a value('test') and sent it to a class function and push the returned value into an array('t'). How can I wait for the for loop to finish and then print the array('t')? I tried using Promises and function wrapper but to no use. Here is the code snippet:

t = []
test = ['1', '2']
for(var i in test) {
    console.log('inside for loop')
    new myFile.class(mysqlParams).myfunc(2, test[i], result=> {
        t.push(result)
        })
    console.log('t: ' + t)
    }

Can someone please help me?

Edit:

myfunc(num, test, callback) {
    connectToMysqlDatabase()
     connection.query(getTestcaseContentCommand, function(err, testContent)  {
      if (err) {
          console.log(err)
       }
       else {
          result(testContent[0]['testcaseContent'])
       }
 }
Karthik
  • 31
  • 1
  • 1
  • 7
  • 3
    Async/await will definitely help you . https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await – Ashraf Dec 24 '20 at 04:40
  • Do you have any control over how `myfunc` is written? If you can write it to where it returns a promise as opposed to using a callback, you can just use `await` inside the loop. – codemonkey Dec 24 '20 at 04:50
  • @Ashraf Thanks for the comment. I'll try it and update – Karthik Dec 24 '20 at 04:52
  • @codemonkey I'm a noob to JS. Looks like I need to learn promises and async. Thanks for the suggestion. – Karthik Dec 24 '20 at 04:53
  • check this out: https://stackoverflow.com/questions/11488014/asynchronous-process-inside-a-javascript-for-loop – sonEtLumiere Dec 24 '20 at 05:00
  • By the way. If you want to rewrite your `myfunc` to use Promises, here is how: https://codesandbox.io/s/interesting-banach-egdvm?file=/test.js – codemonkey Dec 24 '20 at 05:29

3 Answers3

2

Here is how to rewrite your specific code to accomplish what you're trying to accomplish:

const callbackFunc = (param1, param2, callback) => {
    setTimeout(() => callback('Ok'), 1000)
}

let t = []
const test = ['1', '2'];
const promises = [];
for(let i in test) {

    promises.push(new Promise(resolve => {
        callbackFunc(2, test[i], result => {
            resolve(result)
        })
    }))

}

Promise.all(promises)
    .then(result => {
        t = result;
        console.log(t);
    })

Note, that in your case, had myfunc returned a promise instead of a callback, it'd be a bit simpler, but since that's not the case, you need to populate an array with promises and then resolve them all using Promise.all

I would also point out that if your code is iteself inside an async function, you could resolve Promise.all like so: const t = await Promise.all(promises)

codemonkey
  • 7,325
  • 5
  • 22
  • 36
  • Thank you lots. I didnt completely understand the code. Should i `new myFile.class(mysqlParams)` in `const callbackFunc = ` ? – Karthik Dec 24 '20 at 05:23
  • @Karthik callbackFunc was just a placeholder to show how an async function works. You would swap it with `new myFile.class(mysqlParams).myfunc` – codemonkey Dec 24 '20 at 05:31
1

Process transform async to sync in javascript we have 3 ways, include:

If you want I can help you how to process your code, please show more detail. Tks

xuan hung Nguyen
  • 390
  • 3
  • 12
0

A simpler and straight forward solution I created for this when using a promise in a loop is:

(async (files)=> {
  for await (const file of files) {
    await uploadSingleFile(file)
    .then((fileUrl:any)=> {
        console.log(fileUrl);
    })
    .catch((error)=> {
        console.log(error)
    });
  
  console.log(allFilesPath);
})

At one point in my code, according to the logic, I used the solution above. But at another, for await didn't work so I tried using a try, finally:

try {
  for(var index=0; index < allKeys.length; index++) {
      const key = allKeys[index], value = jsonObject[allKeys[index]];

      if(Array.isArray(value)) {
          value.forEach(val => formData.append(key, val))
      } 
      else formData.append(key, value);
  }
} 
finally {
  resolve(formData);
}
Keenlabi
  • 163
  • 1
  • 2
  • 11