Async /await is a special syntax that makes it easy to use promises.

Async indicates that this function will return a promise. If it does not return a promise, it will be wrapped as a resolved promise.

async function f() {
  return 1;
}
f().then(alert); / / 1

// This is equivalent to the following
async function f() {
  return Promise.resolve(1);
}
f().then(alert); / / 1
Copy the code

Await is only valid in async functions. Using await in normal functions results in a syntax error. let value = await promise; This tells the JavaScript engine to wait until the promise completes and returns the result. This behavior does not cost CPU resources because the engine can handle other tasks at the same time: executing other scripts, handling events, and so on.

async function f() {
  let promise = new Promise((resolve, reject) = > {
    setTimeout((a)= > resolve("done!"), 1000)});let result = await promise; // Wait until the promise resolved result is obtained
  alert(result); // "done!"
}
f();
Copy the code

An await can take a Thenable object (an object with a THEN method) and call the THEN method, passing in resolve, reject as arguments. The await then waits until one of the two methods is called and processes the resulting result.

class Thenable {
  constructor(num) {
    this.num = num;
  }
  then(resolve, reject) {
    setTimeout((a)= > resolve(this.num * 2), 1000); }};async function f() {
  // Wait 1 second for result to change to 2
  let result = await new Thenable(1);
  alert(result);
}
f();
Copy the code

If you want to define an async class method, just add async to the method:

class Waiter {
  async wait() {
    return await Promise.resolve(1); }}new Waiter().wait().then(alert); / / 1
Copy the code

Error handling

If a promise was resolved, the await promise returns the result. If a promise is rejected, an error is thrown, just as there is a throw statement on that line.

async function f() {
  await Promise.reject(new Error("Whoops!"));
}
// Equivalent to:
async function f() {
  throw new Error("Whoops!");
}
Copy the code

You can use the try.. To catch the above error, just as you would with a normal throw statement:

async function f() {
  try {
    let response = await fetch('http://no-such-url');
  } catch(err) {
    alert(err); // TypeError: failed to fetch
  }
}
f();
Copy the code

If you don’t use try.. Catch, the promise generated by f() is rejected and can be added after the function call to handle the error. If no errors are handled, the global unhandledrejection event can be used to catch them.

async function f() {
  let response = await fetch('http://no-such-url');
}
// make f() a reject promise
f().catch(alert); // TypeError: failed to fetch // (*)

Copy the code

All can be used with async/await when waiting for more than one promise:

async() = > {let results = await Promise.all([ fetch(url1), fetch(url2), ... ] ); }Copy the code

If an error occurs, it is passed normally: from the failed promise to Promise.all, then to the one we can use to try.. Exception handled by catch.

Execution order

Async/await is promise-based, so it uses the same microtask queue internally and has a higher priority than macro tasks.

async function f() {
  return 1;
}
(async () => {
    setTimeout((a)= > alert('timeout'), 0); / / 3

    await f(); / / 1

    alert('await'); / / 2}) ();Copy the code

In a normal function, how do I call another async function and get the return value? Use THEN because the async function returns a settled promise.

async function wait() {
  await new Promise(resolve= > setTimeout(resolve, 1000));
  return 10;
}
(function() {
  wait().then((value) = >alert(value)); }) ();Copy the code