This is the 29th day of my participation in the August More Text Challenge

Async /await advanced

4.1 Async /await advantages combat

4.1.1 Discard redundant THEN chain code

function takeLongTime(n) {
  return new Promise(resolve= > {
    setTimeout(() = > resolve(n + 200), n);
  });
}

function step1(n) {
  console.log(`step1 with ${n}`);
  return takeLongTime(n);
}

function step2(n) {
  console.log(`step2 with ${n}`);
  return takeLongTime(n);
}

function step3(n) {
  console.log(`step3 with ${n}`);
  return takeLongTime(n);
}
Copy the code

Use the Promise approach to implement these three steps:

function doIt() {
  console.time("doIt");
  const time1 = 300;
  step1(time1)
    .then(time2= > step2(time2))
    .then(time3= > step3(time3))
    .then(result= > {
      console.log(`result is ${result}`);
    });
}
doIt();
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900
Copy the code

If async/await is used:

async function doIt() {
  console.time("doIt");
  const time1 = 300;
  const time2 = await step1(time1);
  const time3 = await step2(time2);
  const result = await step3(time3);
  console.log(`result is ${result}`);
}
doIt();
Copy the code

4.1.2 A more elegant median

function doIt() {
  console.time("doIt");
  const time1 = 300;
  step1(time1)
    .then(time2= > {
      return step2(time1, time2)
        .then(time3= > [time1, time2, time3]);
    })
    .then(times= > {
      const [time1, time2, time3] = times;
      return step3(time1, time2, time3);
    })
    .then(result= > {
      console.log(`result is ${result}`);
    });
}
doIt();
Copy the code

Write async/await:

async function doIt() {
  console.time("doIt");
  const time1 = 300;
  const time2 = await step1(time1);
  const time3 = await step2(time1, time2);
  const result = await step3(time1, time2, time3);
  console.log(`result is ${result}`);
}
doIt();
// step1 with 300
// step2 with 300
// step3 with 300
// result is 500
Copy the code

4.1.3 Easier to debug

You cannot set breakpoints in a returned arrow function because there is no code block. If you use the debugger step-over in a.then block, the debugger does not go into subsequent.then blocks, because the debugger can only track each step of the synchronized code.

Now, if you use async/await, you don’t have to use arrow functions anymore. You can step on await statements as if they were normal synchronous statements.

4.2 Async /await error processing

Since async returns a Promise, we can catch the error outside.

const demo = async() = > {const result = await setDelay(1000);
  console.log(result);
  console.log(await setDelaySecond(2));
  console.log(await setDelay(1000));
  console.log('Done');
}
demo().catch(err= > {
  console.log(err);
})
Copy the code

You can also use try… Catch statement, so there’s no need to catch outside.

(async() = > {try {
    const result = await setDelay(1000);
    console.log(result);
    console.log(await setDelaySecond(2));
    console.log(await setDelay(1000));
    console.log('Done');
  } catch (e) {
    console.log(e); // An error is caught here
  }
})()
Copy the code

But try… A catch can only wrap a block of code. If you need to break the process apart, you don’t want to crash the whole process because of one error. The catch?

(async() = > {const result = await setDelay(1000).catch(err= > {
    console.log(err)
  });
  console.log(result);
  const result1 = await setDelaySecond(12).catch(err= > {
    console.log(err)
  })
  console.log(result1);
  console.log(await setDelay(1000));
  console.log('Done'); }) ()Copy the code

Output result:

I was delayed1000Milliseconds laterErrorThe: parameter must be of type number and must be less than or equal to10
    at Promise (test4.html:19)
    at new Promise (<anonymous>)
    at setDelaySecond (test4.html:18)
    at test4.html:56
undefinedI was delayed1000Milliseconds later the output is completeCopy the code

In this way, errors will not affect subsequent operations. But ‘await’ followed by ‘catch’ is very confusing. It can be improved to encapsulate the code function that extracts the error:

function to(promise) {
  return promise.then(data= > {
    return [null, data];
  }).catch(err= > [err]);
}
Copy the code

Returns an array with the first error and the second asynchronous result as follows:

(async() = > {// es6 returns an array
  // The first is an error message, and the second is asynchronous return data for then
  // Note here that duplicate variable declarations can cause problems
  [err, result] = await to(setDelay(1000))
  // If err exists, it is an error, and does not want to continue
  if (err) throw new Error('There's an error, and I don't want to execute.');
  console.log(result);
  [err, result1] = await to(setDelaySecond(12))
  // Do not throw an error if you still want to execute
  if (err) console.log('There's an error, and I want to continue.', err);
  console.log(result1);
  console.log(await setDelay(1000));
  console.log('Done'); }) ()Copy the code

4.3 Terminate the program async/await

Promise itself cannot be suspended. Promise itself is just a state machine, storing three states (Pending, resolved and Rejected). Once the request is sent, it must be closed and cannot be cancelled. This is usually not allowed to happen, but is used to temporarily stop the chain.

To interrupt async/await, return null, null, false.

let count = 6;
const demo = async() = > {const result = await setDelay(1000);
  console.log(result);
  const result1 = await setDelaySecond(count);
  console.log(result1);
  if (count > 5) {
    return 'I'm out. I'm done.';
    // return; 
    // return false; // All of these can be written
    // return null;
  }
  console.log(await setDelay(1000));
  console.log('Done');
};

demo().then(result= > {
  console.log(result);
}).catch(err= > {
  console.log(err);
})
Copy the code

Resolve (‘ I’m out ‘); you can also return a ‘reject’ : Return promise.reject (new Error(‘ reject ‘)) then it goes into the Error message.