How to use Async/Await to deal with errors

preface

For a long time, Fees had to rely on callbacks to handle asynchronous code. As a result of using callbacks, the code became tangled and difficult to understand and maintain, but thankfully Promise brought along.then(), which made the code neat and manageable. So we’re using it a lot, instead of the callback method. But there is no way for the current execution process to block until the promise completes. In JS, we can’t just wait for a promise to complete, and the only way to plan ahead for the logic to execute after a promise completes is to append callback functions via THEN. Now, with the increase of Async/Await, it is possible to have interfaces get data sequentially asynchronously and handle callbacks in a more readable and maintainable way.

This article describes a better way to handle errors when using the async/await syntax.

compatibility

Async/Await is already available in most major browsers.

Async /await elegant error handling

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
const fetchData = () => {Copy the code    return new Promise((resolve, reject) => {Copy the code        setTimeout(() => {Copy the code            resolve('fetch data is me')Copy the code}, 1000).Copy the code    })Copy the code}Copy the code

Copy the code
(async () => {Copy the code try {Copy the code const data = await fetchData()Copy the code console.log('data is ->', data)Copy the code } catch(err) {Copy the code console.log('err is ->', err)Copy the code }Copy the code}) ()Copy the code

Looks like it’s okay, but what if it is? There are multiple asynchronous operations, and the error status returned by each asynchronous operation needs to be handled differently. Here is sample code.

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
const fetchDataA = () => {Copy the code    return new Promise((resolve, reject) => {Copy the code        setTimeout(() => {Copy the code            resolve('fetch data is A')Copy the code}, 1000).Copy the code    })Copy the code}Copy the code

Copy the code
const fetchDataB = () => {Copy the code return new Promise((resolve, reject) => {Copy the code setTimeout(() => {Copy the code resolve('fetch data is B')Copy the code}, 1000).Copy the code })Copy the code}Copy the code

Copy the code
const fetchDataC = () => {Copy the code return new Promise((resolve, reject) => {Copy the code setTimeout(() => {Copy the code resolve('fetch data is C')Copy the code}, 1000).Copy the code })Copy the code}Copy the code

Copy the code
(async () => {Copy the code try {Copy the code const dataA = await fetchDataA()Copy the code console.log('dataA is ->', dataA)Copy the code } catch(err) {Copy the code console.log('err is ->', err)Copy the code }Copy the code

Copy the code
try {Copy the code const dataB = await fetchDataB()Copy the code console.log('dataB is ->', dataB)Copy the code } catch(err) {Copy the code console.log('err is ->', err)Copy the code }Copy the code

Copy the code
try {Copy the code const dataC = await fetchDataC()Copy the code console.log('dataC is ->', dataC)Copy the code } catch(err) {Copy the code console.log('err is ->', err)Copy the code }Copy the code}) ()Copy the code

Are you comfortable with trying/catching code like this? It might be tempting to just use a try/catch.

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
/ /... Here the fetch function is omittedCopy the code

Copy the code
(async () => {Copy the code try {Copy the code const dataA = await fetchDataA()Copy the code console.log('dataA is ->', dataA)Copy the code const dataB = await fetchDataB()Copy the code console.log('dataB is ->', dataB)Copy the code const dataC = await fetchDataC()Copy the code console.log('dataC is ->', dataC)Copy the code } catch(err) {Copy the code console.log('err is ->', err)Copy the code// Define err type and then decide?Copy the code/ * *Copy the code * if (err.type === 'dataA') {Copy the code* console.log('dataA err is', err)Copy the code*}Copy the code*...Copy the code* * /Copy the code }Copy the code}) ()Copy the code

If this is the case, it will only increase the complexity of coding and write more code. At this time, we should think about how to solve the problem gracefully. Async /await is essentially the syntax candy of promise, since it is a promise, we can use then function.

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
(async () => {Copy the code    const fetchData = () => {Copy the code        return new Promise((resolve, reject) => {Copy the code            setTimeout(() => {Copy the code                resolve('fetch data is me')Copy the code}, 1000).Copy the code        })Copy the code    }Copy the code

Copy the code
const data = await fetchData().then(data => data ).catch(err => err)Copy the code console.log(data)Copy the code}) ()Copy the code

FetchData (‘ resolve ‘, ‘reject’, ‘data’); fetchData (‘ resolve ‘, ‘reject’, ‘data’);

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
(async () => {Copy the code    const fetchData = () => {Copy the code        return new Promise((resolve, reject) => {Copy the code            setTimeout(() => {Copy the code                resolve('fetch data is me')Copy the code}, 1000).Copy the code        })Copy the code    }Copy the code

Copy the code
const [err, data] = await fetchData().then(data => [null, data] ).catch(err => [err, null])Copy the code console.log('err', err)Copy the code console.log('data', data)Copy the code // err nullCopy the code // data fetch data is meCopy the code}) ()Copy the code

Isn’t that much better, but the problem is again, you can’t write every await so long, it’s not convenient and elegant to write, so optimize it.

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
(async () => {Copy the code    const fetchData = () => {Copy the code        return new Promise((resolve, reject) => {Copy the code            setTimeout(() => {Copy the code                resolve('fetch data is me')Copy the code}, 1000).Copy the code        })Copy the code    }Copy the code

Copy the code
// Extract into a public methodCopy the code const awaitWrap = (promise) => {Copy the code return promiseCopy the code .then(data => [null, data])Copy the code .catch(err => [err, null])Copy the code }Copy the code

Copy the code
const [err, data] = await awaitWrap(fetchData())Copy the code console.log('err', err)Copy the code console.log('data', data)Copy the code // err nullCopy the code // data fetch data is meCopy the code}) ()Copy the code

Isn’t it more elegant to call a method such as awaitWrap with await while separating the method from the public method to await it? This is what the typescript implementation would look like.

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
function awaitWrap<T, U = any>(promise: Promise<T>): Promise<[U | null, T | null]> {Copy the code    return promiseCopy the code        .then<[null, T]>((data: T) => [null, data])Copy the code        .catch<[U, null]>(err => [err, null])Copy the code}Copy the code

summary

Async/Await lets us use promises in small amounts of code. We can put some dependent callback processing logic inside Async and use it in non-async areas to reduce then or catch callbacks.