0

If I run putToDeath(0, 1).then(()=>{ console.log('done') } the console outputs done before setAsyncTimeout 463. So my function is not awaiting everything, it's returning prematurely.

How do I make it await until the very last function call, face(exeNum, 'walk', true), is made?

async function putToDeath(conNum, exeNum) {
      let exeStartX = round(players[exeNum].x)
      let exeStartY = round(players[exeNum].y)
      console.log('walkTo 452')
      await walkTo(conNum, window.innerWidth / 2, window.innerHeight / 2, 0.5).then(async() => {
        faceAudience(conNum, 'walk')
        console.log('setAsyncTimeout 455')
        await setAsyncTimeout(async() => {
          let exe = players[exeNum]
          let direction = pointDirection(exe.x, exe.y, window.innerWidth / 2, window.innerHeight / 2)
          let distance = lineLength(exe.x, exe.y, window.innerWidth / 2, window.innerHeight / 2)
          let dest = getLineEndpoint(exe.x, exe.y, direction, distance - 50)
          console.log('walkTo 461')
          await walkTo(exeNum, dest.x, dest.y, 0.75).then(async() => {
          console.log('setAsyncTimeout 463')
            await setAsyncTimeout(async() => {
              swingSword(exeNum)
              await setAsyncTimeout(async() => {
                await die(conNum).then(async() => {
                  await setAsyncTimeout(async() => {
                    face(exeNum, 'walk', false)
                    await setAsyncTimeout(async() => {
                      await walkTo(exeNum, exeStartX, exeStartY, 0.75).then(async() => {
                        face(exeNum, 'walk', true)
                      })
                    }, 500)
                  }, 500)
                })
              }, 750)
            }, 500)
          })
        }, 1000)
      })
    }
const setAsyncTimeout = (cb, timeout = 0) => new Promise(resolve => {
      setTimeout(() => {
        cb()
        resolve()
      }, timeout)
    })
Meler Lawler
  • 165
  • 1
  • 8

1 Answers1

3

There is no need to mix callbacks and Promises. There is also no need to mix .then and await. Turn your promising timer into:

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

Then use it as:

await walkTo(conNum, window.innerWidth / 2, window.innerHeight / 2, 0.5);
faceAudience(conNum, 'walk')
console.log('setAsyncTimeout 455')    
await setAsyncTimeout(1000);

swingSword(exeNum);
await setAsyncTimeout(1000);

await die(conNum);
await setAsyncTimeout(1000);

face(exeNum, 'walk', false);
await setAsyncTimeout(1000);

await walkTo(exeNum, exeStartX, exeStartY, 0.75);
face(exeNum, 'walk', true);
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • Awesome! This allowed me to make all the rest of my code more readable as well. – Meler Lawler Nov 08 '19 at 20:39
  • I wanted to ask how to execute an array of async function calls in series (one after the other), NOT in parallel, not simultaneously. `await f(0); await f(1)` works but `;[0, 1].forEach(i => { await f(i) })` executes both calls at once. I want them done in order, not moving to the next until the first is complete. – Meler Lawler Nov 09 '19 at 00:04
  • 1
    https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop – Jonas Wilms Nov 09 '19 at 00:05
  • 1
    Don't know why you are banned, probably not because of this post. If you think the ban is incorrect (!= unfair) flag for a moderator, they can tell you why that happened. – Jonas Wilms Nov 09 '19 at 00:06
  • Thanks, `for ... of` does exactly what I want to do. I am certain it's because of this question because I haven't posted in a long time, then I post this and bam, banned within 3 hours. Apparently there is a zero reinstatement policy so I gain nothing from inquiring further. – Meler Lawler Nov 09 '19 at 00:10
  • Thanks I do admit I'm curious as to what happened. – Meler Lawler Nov 09 '19 at 00:21