-1

Hello Stack Overflow community, I come to you with a problem related to JS async/await. I am trying to call an async function and then log the array to where the async function pushes the results to the console. If I call it like so directly in the console:

console.log(Page.data) - I can see that it has results in it, but if it is called on click of a button it logs an empty array.

// It is a nested object so do not worry if you don't exactly understand where Page.data comes from
Page.data = []

async function f1() {
  // Fetch JSON data
  // Process data 
  // Pushes at some point to the Page.data array
}
async function f2() {
  // Fetch JSON data
  // Process data 
  // Pushes at some point to the Page.data array
}
async function f3() {
  // Fetch JSON data
  // Process data 
  // Pushes at some point to the Page.data array
}

async function load(loader) {
    let fn = async function() {};
    if(condition1) fn = f1;
    else if(condition2) fn = f2;
    else fn = f3;

    // This is the line that makes me problems
    // According to documentation async functions return a promise
    // So why would the array in the case be empty?
    // Since I am telling it to display after the function is done
    await fn(loader).then(console.log(Page.data))
}

This is just a template of my code and logic. I hope that you can understand where I am going. Your help will be much appreciated.

Andreas
  • 39
  • 5
  • 3
    You either `await` a promise, which gets you the resolution value, or you use `promise.then(...)` in order to have code kick in once the promise resolves. Pick either, not both. – Mike 'Pomax' Kamermans Jan 22 '20 at 13:43
  • @Mike'Pomax'Kamermans so you are suggesting i should do fn().then()? – Andreas Jan 22 '20 at 13:46
  • `await fn(loader); console.log(Page.data);` – JLRishe Jan 22 '20 at 13:47
  • since you used the await keyword then you can just do: `await fn(loader); console.log(Page.data);` – VirxEC Jan 22 '20 at 13:48
  • or just don't use the await keyword and it might work – VirxEC Jan 22 '20 at 13:49
  • Does this answer your question? [async/await implicitly returns promise?](https://stackoverflow.com/questions/35302431/async-await-implicitly-returns-promise) – Tân Jan 22 '20 at 13:50
  • Oh... it actually works if I remove await and use then. the console output was [] so I thought it is empty but when I opened, it had 1 result in it – Andreas Jan 22 '20 at 13:50
  • @Tân thankyou, I knew that an async function returns a promise, apparently the code has probably been working all the time but since console was printing >[] all the time i thought it didn't – Andreas Jan 22 '20 at 14:20
  • console.log return undefined, not a function. – Sodala Jan 22 '20 at 15:11

2 Answers2

2

The await expression causes async function execution to pause until a Promise is settled (that is, fulfilled or rejected), and to resume execution of the async function after fulfillment. When resumed, the value of the await expression is that of the fulfilled Promise.

For instance (this is an MDN example with some added comments):

function resolveAfter2Seconds(x) { 
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  // note that here, you are "awaiting" the RESOLVED RESULT of the promise.
  // there is no need to "then" it.
  var x = await resolveAfter2Seconds(10);
  // the promise has now already returned a rejection or the resolved value. 
  console.log(x); // 10
}

f1();

So you would "await" your function, which would hold up the execution until the promise either resolves or rejects. After that line, you would run your console.log, and it would log as expected. Short answer, "remove the then".

I should add, if the result of the "awaited" function is not a promise, it is converted to a promise (so technically, there is no need to return a promise, it'll wrap up your returned value for you).

Tim Consolazio
  • 4,802
  • 2
  • 19
  • 28
0

the problem is that you can use then with await for the same method, lets check some examples provided by MDN:

this is a working Promise using async/await:

let myFirstPromise = new Promise((resolve, reject) => {
  setTimeout(function() {
    resolve("Success!");
  }, 250)
})

const functionCaller = async() => {
  const result = await myFirstPromise
  console.log("the result: ", result);
}

functionCaller();

what you are trying is:

let myFirstPromise = new Promise((resolve, reject) => {
  setTimeout(function() {
    resolve("Success!");
  }, 250)
})

const functionCaller = async() => {
  // you are not returning anything here... actually you are not doing anything with the response. despite it shows something, it is not sending any response
  await myFirstPromise.then(console.log("something happened"))

}
// then this function doesn't really get a value.
functionCaller();

so what you need to do in your load call, is to change it like this:

async function load(loader) {
    let fn = async function() {};
    if(condition1) fn = f1;
    else if(condition2) fn = f2;
    else fn = f3;

    return await fn(loader)
}
Prince Hernandez
  • 3,623
  • 1
  • 10
  • 19