2

I'm struggling with the async/await function in javascript.

Here's the example code I wrote.

const function1 = async () => {
    setTimeout(() => {
        console.log('function 1 finished');
        return 'message';
    }, 500);
};

const funtcion2 = async () => {
    const result1 = await function1();
    console.log('result1: ', result1);
};

funtcion2();

It resulted the below, which I don't quite understand.

result1:  undefined
function 1 finished

Please could anyone help me correcting the code, so that I can get something like the below.

result1:  'message'
function 1 finished
asounrb
  • 29
  • 2
  • The timer facility will always ignore any values returned from timer handler functions. – Pointy Oct 03 '22 at 03:27
  • 2
    returning from a setTimeout callback is not the same as returning from a function – nullptr Oct 03 '22 at 03:28
  • Thank you for your comment, which helped a lot. I would like to ask you two more questions 1. Thought the async function will return a promise, which will be used with await in the function2. And according to @nullptr 's comment, is that the reason why the await did not work as I wanted? 2. If the function1 had returned without setTimeout, would it have worked as I thought it would have worked? – asounrb Oct 03 '22 at 03:44

2 Answers2

2

function1 needs to return the result of that setTimeout function as a Promise in order to be awaited and shown the result.

So, you need to create a Promise and return it like this:

const function1 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('function 1 finished');
      resolve('message');
    }, 500);
  });
};

const funtcion2 = async () => {
  const result1 = await function1();
  console.log('result1: ', result1);
};

funtcion2();
technophyle
  • 7,972
  • 6
  • 29
  • 50
  • When a function returns a `Promise` like that, you don't need to add `async`. At the moment, `function1` as you have it written actually returns a `Promise` that resolves to a `Promise` that resolves to a `string`. The `await` keyword can do a fine job of resolving nested Promises like this, but it's worth being aware of. – Mark Hanna Oct 03 '22 at 03:39
  • 1
    Yeah you're right. I just copy/pasted his original code and edited it. – technophyle Oct 03 '22 at 03:43
  • Easy enough to fix :) – Mark Hanna Oct 03 '22 at 03:47
1

When you mark a function as async, you're essentially making it return a new Promise object that resolves to whatever the function returns, and rejects if the function throws an error.

That means there are two ways to write simple async functions. These are both equivalent:

async function foo(data) {
    return JSON.parse(data);
}
function foo(data) {
    return new Promise((resolve, reject) => {
        try {
            resolve(JSON.parse(data));
        } catch (e) {
            reject(e);
        }
    });
}

Of course, the async keyword lets you write simple asynchronous functions much more concisely and use more familiar syntax. But there are times where this isn't enough, because you can't actually return the value you want your Promise to resolve to.

Usually you can retrieve a value asynchronously within an async function using the await keyword, but there are exceptions. Your example here is one of these exceptions.

Because your asynchronous function1 is not returning anything, so the Promise resolves to undefined. You should write your function to return a Promise explicitly instead, so you can make sure it resolves with the value you want once that value is ready. Like this:

const function1 = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('function 1 finished');
            resolve('message');
        }, 500);
    });
};
Mark Hanna
  • 3,206
  • 1
  • 17
  • 25