blankface
blankface

Reputation: 6347

Array defined outside of function not being populated after awaiting an async call

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?

Upvotes: 1

Views: 63

Answers (2)

Feiga Lubow
Feiga Lubow

Reputation: 332

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();

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370989

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

Upvotes: 4

Related Questions