Использование setTimeout в асинхронной функции - PullRequest
0 голосов
/ 06 июля 2018

У меня есть асинхронная функция, которая ожидает завершения вызова axios, прежде чем продолжить. Проблема в том, что мне нужно установить тайм-аут на вызов axios на полсекунды, чтобы не превышать предел вызовов API shopify.

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)
}

Когда я пытаюсь установить setTimeout, он вызывает setTimeout и продолжает работу до завершения вызовов axios.

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)
}

Любая помощь?

Ответы [ 5 ]

0 голосов
/ 06 июля 2018

Вам нужно создать новое обещание, например, подобное

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

А затем используйте его в своем коде перед вызовом API

...
await delay(500)
await axios.get(item).then((res) => {
...
0 голосов
/ 06 июля 2018

setTimeout() не возвращает Promise, но вы можете обернуть его в один такой. Я также немного очистил остальную часть вашего кода.

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

    await axios.get(item).then((res) => {
      Object.values(res.data.metafields).filter(
        ({ value }) => value === schoolName
      ).forEach(({ owner_id }) => {
        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)
}
0 голосов
/ 06 июля 2018

Создайте функцию sleep, которая возвращает обещание, которое вы можете использовать, например:

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

И использовать его в асинхронной функции:

(async () => {
  console.log("function invoked...")
  await sleep(500)
  console.log("I got here about 500 milliseconds later")
})()
0 голосов
/ 06 июля 2018

setTimeout не возвращает обещание, поэтому не может быть await ed.

Вы можете создать свое собственное обещание setTimeout и использовать его.

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

await setTimeoutPromise(500);
0 голосов
/ 06 июля 2018

await работает только на обещаниях. Вам нужно завернуть setTimeout в обещание:

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

await waitFor(500);
...