Forcing a function to wait until another function is complete

Viewed 7876

I am new to JavaScript and have been trying to get this working for a while now but to no success.

I have a function (task 3) that should only be executed after the functions before it finish. The functions before it (task 1 and 2) have more functions in them that fetch data from other sources and the time it takes for them is unknown. A wait function wouldn't really work because the time for task 1 and 2 could be very fast or very slow. I have tried doing an async/await setup but i must have done it wrong because it always completed task 3 before task 1 or 2. Same with a callback function which didn't actually callback it just did task 1 and 2 then never did task 3.

function task1(input){
   // has more functions that do other stuff

}
function task2(input){
   // has more functions that do other stuff
}
function task3(input){
   // this code should only be executed after both task 1 and 2 finish
}

function main(input1, input2, input3){
    task1(input1); // doesn't matter which task finishes first between 1 and 2
    task2(input2);
    task3(input3); // task 3 should not be executed until task 1 and 2 have completed.
}

main(input1, input2, input3);

If anyone could help that would be greatly appreciated.

3 Answers

It sounds like your environment supports async/await. So assuming that task1 and task2 either are async or return a Promise, then:

  1. Use await Promise.all to wait for the two tasks to complete. This does not enforce any order, but will ensure both have completed before moving on.
  2. Call task3.
    async function task1(input){
       // has more functions that do other stuff

    }
    async function task2(input){
       // has more functions that do other stuff
    }

    function task3(input){
       // this code should only be executed after both task 1 and 2 finish
    }

    async function main(input1, input2, input3){
        await Promise.all(
            task1(input1),
            task2(input2)
        )
        task3(input3);
    }

    main(input1, input2, input3);

You want to use promises if you have asynchronous code. Promise.all() will wait for them all to be complete before running.

function task1() {
  return new Promise(function(resolve, reject) {
    console.log("task 1")
    setTimeout(function() {
      resolve('foo');
    }, Math.random() * 2000);
  })
}

function task2() {
  return new Promise(function(resolve, reject) {
    console.log("task 2")
    setTimeout(function() {
      resolve('bar');
    }, Math.random() * 2000);
  })
}

function task3() {
  console.log("task 3")
}

Promise.all([task1(), task2()]).then(function(values) {
  console.log(values);
  task3()
});

Since you said you are using fetch, you can use that instead of promises since that returns a promise.

function task1() {
  return fetch('http://example.com/foo.json')
    .then(response => response.json())
}

function task2() {
  return fetch('http://example.com/bar.json')
    .then(response => response.json())
}

function task3() {
  console.log("task 3")
}

Promise.all([task1(), task2()]).then(function(values) {
  console.log(values);
  task3()
});

Since you're making API calls in your tasks, each task should be defined as an asynchronous function, and awaited as follows:

const fetch = require('node-fetch')

async function task1(input){
  console.log(input)
  // API call goes here
  // const response = await fetch("http://localhost:5000/endpoint")
  console.log(response)
}
async function task2(input){
  console.log(input)
}
async function task3(input){
  console.log(input)
}

async function main(input1, input2, input3){
   await task1(input1); // doesn't matter which task finishes first between 1 and 2
   await task2(input2);
   await task3(input3); // task 3 should not be executed until task 1 and 2 have completed.
}

main("LIONS", "TIGERS", "BEARS")

You'll see the above results in:

LIONS
TIGERS
BEARS

and any API calls will occur in sequence.

Related