1

I have the following code where in the getStuff function I'm making an external async call and storing the result in result. From there I'm looping over result.Content.Ids and pushing the Ids in myArray.

When getStuff() gets called in run(), further down the code I need to access myStuff array but if I console.log it out, it shows up as empty.

const myArray = [];

const getStuff = async (val) => {
    const other = {}

    if(val) other.newestVal = val;

    const result = await someCall(other);

    result.Content.Ids.forEach((id) => myArray.push(id));

    if (result.AFieldExists) {
        getStuff(result.newVal)
    }
}

const run = async () => {
    await getStuff();

    // other code below that uses myArray
    // but its empty when I log it
}

run();

I'd have expected myArray to be populated since I'm awaiting getStuff() in run(). What am I doing wrong here?

blankface
  • 5,757
  • 19
  • 67
  • 114
  • [I cannot reproduce it](https://jsbin.com/qusumib/1/edit?js,console) – VLAZ Jun 03 '21 at 06:48
  • try to await `getStuff()` inside the recursive call too – Deiknymi Jun 03 '21 at 06:53
  • @VLAZ that's probably because your code example doesn't makes a recursive call. – Yousaf Jun 03 '21 at 06:55
  • 1
    @Yousaf it was supposed to be a gentle reminder that there is no [mcve] in the post. But yes, you're right. To be clear "this code doesn't work" with no indication *how* it should work and *when* it fails, are *more* work for us to answer and shouldn't be. Given how easy is to mock the `someCall` (see snippet) there is really no reason to withhold reproduction steps from us. – VLAZ Jun 03 '21 at 08:07

2 Answers2

4

Your recursive call:

if (result.AFieldExists) {
    getStuff(result.newVal)
}

is incorrect, since you're not waiting for the result - only the first getStuff call will be waited for. You need:

const getStuff = async (val) => {
    const other = {}

    if(val) other.newestVal = val;

    const result = await someCall(other);

    result.Content.Ids.forEach((id) => myArray.push(id));

    if (result.AFieldExists) {
        return getStuff(result.newVal)
    }
}

You can also clean it up a bit to avoid the ugly outer variable:

const getStuff = async (val, output = []) => {
    const other = {}
    if (val) other.newestVal = val;
    const result = await someCall(other);
    output.push(...result.Content.Ids);
    return result.AFieldExists
        ? getStuff(result.newVal, output)
        : output;
}

const run = async () => {
    const output = await getStuff(); // pass initial value here?
}
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Here I don't want to return `result` though. I want to return the `output` array. Also do I need to await the getStuff recursive call too? – blankface Jun 03 '21 at 06:51
0

you need to put your await calls in try{} catch(){}, and also your recursive call to getStuff() was with out the key word await :

    async function someCall() {
  return {
    Content: {Ids: [1, 2, 3]}
  }
}


const myArray = [];



const getStuff = async (val) => {
    const other = {}
    let result;
    if(val) other.newestVal = val;
try{
    result = await someCall(other);
}catch(err){
console.log('error from some call' ,err);
}
console.log(myArray)
    result.Content.Ids.forEach((id) => myArray.push(id));
console.log(myArray)

    if (result.AFieldExists) {
        try{
        await getStuff(result.newVal)
        }catch(err){
            console.log('error from get stuff in get stuff' , err);
        }
    }
}

const run = async () => {
    console.log("run")
  try{
    await getStuff();
  }catch(err){
      console.log('error' , err);
  }
    console.log("end run")
console.log(myArray)
    // other code below that uses myArray
    // but its empty when I log it
}

run();
Feiga Lubow
  • 194
  • 3
  • 12