24

I have a async function that waits for an axios call to complete before proceeding. The problem is that I need to put a timeout on the axios call to half a second so that I don't hit the shopify API call limit.

async function processMatchingSchools(customer_metafield_url) {
  for (const item of customer_metafield_url) {
    await axios.get(item).then((res) => {
      for (key in res.data.metafields) {
        if (res.data.metafields[key].value === schoolName) {
          id_for_each_student.push(shopifyAdmin + "/customers/" + res.data.metafields[key].owner_id + "/metafields.json")
        }
      }
    })
  }
  console.log("Customer metafields to search", id_for_each_student)
  processOwnerIds(id_for_each_student)
}

when I try putting a setTimeout, it calls the setTimeout and moves on before completing the axios calls.

async function processMatchingSchools(customer_metafield_url) {
  for (const item of customer_metafield_url) {
    await setTimeout(function(item) {
      axios.get(item).then((res) => {
        for (key in res.data.metafields) {
          if (res.data.metafields[key].value === schoolName) {
            id_for_each_student.push(shopifyAdmin + "/customers/" + res.data.metafields[key].owner_id + "/metafields.json")
          }
        }
      })
    }, 500)
  }
  console.log("Customer metafields to search", id_for_each_student)
  processOwnerIds(id_for_each_student)
}

Any help?

user7637745
  • 965
  • 2
  • 14
  • 27
Matthew Werdean
  • 375
  • 1
  • 2
  • 7

6 Answers6

41

await only works on promises. You need to wrap setTimeout in a promise:

const waitFor = delay => new Promise(resolve => setTimeout(resolve, delay));

await waitFor(500);
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
26

setTimeout() doesn't return a Promise, but you can wrap it in one like this. I also cleaned up the rest of your code a little.

async function processMatchingSchools(customer_metafield_url) {
  for (const item of customer_metafield_url) {
    await new Promise(resolve => {
      setTimeout(resolve, 500)
    })

    const { data: { metafields } } = await axios.get(item)

    for (const { value, owner_id } of Object.values(metafields)) {
      if (value === schoolName) {
        id_for_each_student.push(`${shopifyAdmin}/customers/${owner_id}/metafields.json`)
      }
    }
  }

  console.log("Customer metafields to search", id_for_each_student)

  processOwnerIds(id_for_each_student)
}
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
9

setTimeout does not return a promise so cannot be awaited.

You could create your own promise-based setTimeout and use that.

const setTimeoutPromise = timeout => new Promise(resolve => {        
  setTimeout(resolve, timeout);
});

await setTimeoutPromise(500);
Alan Friedman
  • 1,582
  • 9
  • 7
6

Create a sleep function that returns a promise that you can use, like so:

const sleep = (milliseconds=500) => new Promise(resolve => setTimeout(resolve, milliseconds))

And to use it in an async function:

(async () => {
  console.log("function invoked...")
  await sleep(500)
  console.log("I got here about 500 milliseconds later")
})()
Lance Whatley
  • 2,395
  • 1
  • 13
  • 16
4

You need to to create new promise for example like that

function delay(ms){
 return new Promise(resolve => setTimeout(resolve, ms))
}

And then use it in your code before calling API

...
await delay(500)
await axios.get(item).then((res) => {
...
undg
  • 787
  • 4
  • 14
3

I created setTimeout2 function that works the same just as a promise:

const setTimeout2 = (callback, ms) => {
  return new Promise(resolve => setTimeout(() => {
    callback();
    resolve();
  }, ms));
} 

So, altogether (noticed the setTimeout2 change):

async function processMatchingSchools(customer_metafield_url) {
  for (const item of customer_metafield_url) {
    await setTimeout2(function(item) {
      axios.get(item).then((res) => {
        for (key in res.data.metafields) {
          if (res.data.metafields[key].value === schoolName) {
            id_for_each_student.push(shopifyAdmin + "/customers/" + res.data.metafields[key].owner_id + "/metafields.json")
          }
        }
      })
    }, 500)
  }
  console.log("Customer metafields to search", id_for_each_student)
  processOwnerIds(id_for_each_student)
}
arielhasidim
  • 694
  • 10
  • 19