skip to Main Content
    async function foo() {
    try {
      const response = await fetch("https://www.xxx.xxx");
      const data = await response.json();
      console.log(data);
    } catch (e) {
        console.log("Error!!: ", e);
      }
    }
    foo();
    console.log('111');

Assuming that there is a code like this, the execution result is

111 -> Error: TypeError: Failed to fetch

And that’s what happens when I think about the execution context process, depending on the code flow

  1. When the foo function is called, the execution context of the foo function is created and added to the call stack.

  2. When fetch ("https://www.xxx.xxx ") runs within the try block, the execution context of the fetch function is created and added to the call stack. This is when a network request is made in the background. The fetch function returns a Promise and the execution context of the fetch function is removed from the call stack.

  3. subsequent actions after the await keyword are added to the micro-task queue.

  4. The foo function ends, removing the execution context of the foo function from the call stack.

  5. console.log (‘111) is executed and "111" is output to the console.

  6. Since the call stack is empty, subsequent operations after await that were queued in the micro-task queue are sequentially moved to the call stack and executed.

  7. The fetch function’s network request fails and a reject is called, causing Promise’s status to be rejected.

  8. How do you catch an error???

The try/catch statement is a little confusing.

In order for console.log (‘111) to run, the call stack must be empty, but how does the catch in the foo function that has already ended get an error??

please help me!

3

Answers


  1. maybe this points can help you :

    1. console.log(111) is called before foo() promise completion.
    2. To catch thrown error of foo(), you need to add .catch(err => ...)
    3. You need to throw the exception in the catch clause if you want to catch it externally, (or do not try-catch)

    Note, you can add await before the call to foo in order to have sequential calls after, thus console.log(111) will be called after promise completion

    Login or Signup to reply.
  2. Since your foo() is async, everything after await is executed async, so after console.log('111') which is sync. So use await foo() to wait for foo() to be settled (resolved or rejected) before console.log('111'). If you want to catch an error from foo() you should rethrow your error.

    Regarding your question what happens with the call stack I wouldn’t bother, but I would imagine async/await as substitution of .then().catch() so basically after await and in a catch block you have completely different functions placed in a call stack in the moment of their executions. The only problem that after await for example you have assess to variables defined before await. Consider it as magic of attaching one scope to another…

    async function foo() {
        try {
          const response = await fetch("https://www.xxx.xxx");
          const data = await response.json();
          console.log(data);
        } catch (e) {
            console.log("Error!!: ", e);
            throw e;
          }
        }
    (async() => {
        try{
           await foo();
        }catch(e){
           console.log(e.message);
        }
        console.log('111');
    })();

    Some scope magic:
    enter image description here

    (async () => {
    
      const test = true;
      await new Promise(resolve=>setTimeout(resolve));
      debugger;
    
    })();
    Login or Signup to reply.
  3. In order for console.log(‘111) to run, the call stack must be empty, but how does the catch in the foo function that has already ended get an error??

    You have it the wrong way around. The call stack has to be empty in order to continue from await fetch()

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search