0

I have a problem, I tried to use async function to make API call but then() doesn't wait until the async function return the promise.

async function :

async function FgetFloorplansByFolder (idProject,idFolder, data = [], hasMore = false, lastSyncedAt = null) {
  axios.get(API_URL, {
    params:{
      'last_synced_at':lastSyncedAt
    },
      headers: {
        'Authorization': API_TOKEN,
        'Accept': 'application/json'
    }
  })

  .then((response) => {
    let XHasMore = response.headers['x-has-more'];
    let lastSyncedAt = response.headers['x-last-synced-at'];
    for(var i in response.data) {
      if(response.data[i].folder_id != null || response.data[i].folder_id == idFolder){
        data.push(response.data[i])
      }
    }
    if(XHasMore == 'true'){
       FgetFloorplansByFolder(idProject,idFolder, data, XHasMore, lastSyncedAt)
    }
    else {
      console.log(data);
      return data
    }
  })
  .catch((err) => {
    return Promise.reject(err)
  })
}

call of async function :

await FgetFloorplansByFolder(req.params.idProject, req.params.idFolder)
.then((result) => {
  console.log(result);
})
.catch((error)=>{
  console.log(error);
})

The expected result is : then function in the call wait until getFloorplansByFolders finish his recursive call and return data before print result in then. But then is printing undefined and doesn't wait until async function finish his call.

How can I do ?

3
  • 3
    Don't mix await and .then() Commented Oct 22, 2020 at 16:39
  • 3
    Your FgetFloorplansByFolder doesn't return the axios.get() result, so nothing else will wait for that call to complete nor would you get the response. Commented Oct 22, 2020 at 16:39
  • Is response.data an array? If so, for-in isn't the right tool to use to loop through it. More in this answer. Commented Oct 22, 2020 at 16:45

1 Answer 1

2

Nothing in the code tells the function that it should wait for that promise to settle, so it doesn't.

In general, don't mix async/await with .then/.catch/.finally (though there are exceptions), use one or the other.

In this case, you can either

  1. Remove the async and just put return in front of the call to axios to return the promise chain; or

  2. Switch to using await within the function

(In both cases, I strongly urge you to remove the .catch handler that converts rejection into fulfillment with undefined; instead, let the caller see the rejection so they know the operation failed.)

#1 looks something like this (note comments):

// 1. No `async`
function FgetFloorplansByFolder (idProject,idFolder, data = [], hasMore = false, lastSyncedAt = null) {
  // 2. Return the promise chain
  return axios.get(API_URL, {
    params:{
      'last_synced_at':lastSyncedAt
    },
      headers: {
        'Authorization': API_TOKEN,
        'Accept': 'application/json'
    }
  })

  .then((response) => {
    let XHasMore = response.headers['x-has-more'];
    let lastSyncedAt = response.headers['x-last-synced-at'];
    for(var i in response.data) {
      if(response.data[i].folder_id != null || response.data[i].folder_id == idFolder){
        data.push(response.data[i])
      }
    }
    if(XHasMore == 'true'){
       // 3. Return the promise from the recursive call
       return FgetFloorplansByFolder(idProject,idFolder, data, XHasMore, lastSyncedAt)
    }
    else {
      console.log(data);
      return data
    }
  });
  // 4. Don't put a `.catch` here -- let the caller know the operation failed
}

#2 looks something like this:

async function FgetFloorplansByFolder (idProject,idFolder, data = [], hasMore = false, lastSyncedAt = null) {
  const response = await axios.get(API_URL, {
    params:{
      'last_synced_at':lastSyncedAt
    },
      headers: {
        'Authorization': API_TOKEN,
        'Accept': 'application/json'
    }
  });
  let XHasMore = response.headers['x-has-more'];
  let lastSyncedAt = response.headers['x-last-synced-at'];
  for(var i in response.data) {
    if(response.data[i].folder_id != null || response.data[i].folder_id == idFolder){
      data.push(response.data[i])
    }
  }
  if(XHasMore == 'true'){
     // 3. Return the result of the recursive call
     return FgetFloorplansByFolder(idProject,idFolder, data, XHasMore, lastSyncedAt)
  }
  else {
    console.log(data);
    return data;
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

First solution works but only in case of the recursive call is not trigger. How to do if the recursive call is trigger ?
@CMICHEL - Note the comment in the code: "If this is an asynchronous operation, note that nothing is waiting for it to complete" I didn't twig to the fact that that's the same function, so yes, it's asynchronous. I'll update it, but hopefully it's clear what you need to do?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.