---
id: 69e1f5fa037cd7c2c4d6b8eb
title: Step 29
challengeType: 0
dashedName: step-29
---

# --description--

Finally, you need to deal with the `catch` method. First, nest the `fetch` statement, the `json` statement, and the displayAuthors call into a `try` block within `initialFetch`. Then, modify the chained `catch` method to be a catch block instead as per the example shown below.

```js
try {
  // code that can cause or throw an error goes in this block
} catch (error) {
  // error handling code here
}
```

If you've done this correctly, the `try` block will contain three lines of code in it and the `catch` block will contain just one line of code. Also, the `SyntaxError` will be resolved and the app should function normally.

Give yourself a pat on the back! You have learned how to make your asynchronous code more readable using the `async` and `await` operators! Now your author page is complete.

# --before-all--

```js
const testData = [{ author: 'Whoever', image: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==', url: "http://not-a-real-url.nowhere/", bio: 'words go here' }];
window.fetch = () => Promise.resolve({json: () => Promise.resolve(testData)});
```  

# --hints--

You should create a `try/catch` block

```js
assert.match(code, /try\s*\{[\s\S]*?\}\s*catch\s*\([^)]*\)\s*\{/);
```

The `catch` should no longer be a chained method

```js
assert.notMatch(code, /\.catch/);
```

The `try` block should contain the three statements that fetch the data, create the `json` and then display it.

```js
const tryBlockRegex =
  /try\s*\{([\s\S]*?)\}(?=\s*(catch|finally)\b|\s*$)/;

const fetchLineRegex = 
  /const\s+res\s*=\s*await\s+fetch\(\s*('|"|`)https:\/\/cdn\.freecodecamp\.org\/curriculum\/news\-author\-page\/authors\.json\1,*\s*\)/;

const jsonLineRegex =
  /authorDataArr\s*=\s*await\s+res\.json\(\)/;

const displayLineRegex =
  /displayAuthors\(authorDataArr\.slice\(startingIndex,\s*endingIndex\)\)/;

const match = code.match(tryBlockRegex);

assert.isDefined(match);

const tryBlockContents = match[1];

assert.isTrue(fetchLineRegex.test(tryBlockContents));
assert.isTrue(jsonLineRegex.test(tryBlockContents));
assert.isTrue(displayLineRegex.test(tryBlockContents));
```

The fCC Authors Page should be rendering correctly

```js
assert.equal(document.querySelector('.author-name').innerText, `Whoever`);
assert.equal(document.querySelector('img')?.getAttribute('alt'), `Whoever avatar`);
```

# --seed--

## --seed-contents--

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>freeCodeCamp News Author Page</title>
    <link rel="stylesheet" href="./styles.css" />
  </head>
  <body>
    <h1 class="title">freeCodeCamp News Author Page</h1>

    <main>
      <div id="author-container"></div>
      <button class="btn" id="load-more-btn">Load More Authors</button>
    </main>

    <script src="./script.js"></script>
  </body>
</html>
```

```css
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  --main-bg-color: #1b1b32;
  --light-grey: #f5f6f7;
  --dark-purple: #5a01a7;
  --golden-yellow: #feac32;
}

body {
  background-color: var(--main-bg-color);
  text-align: center;
}

.title {
  color: var(--light-grey);
  margin: 20px 0;
}

#author-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.user-card {
  border-radius: 15px;
  width: 300px;
  height: 350px;
  background-color: var(--light-grey);
  margin: 20px;
}

.user-img {
  width: 150px;
  height: 150px;
  object-fit: cover;
}

.purple-divider {
  background-color: var(--dark-purple);
  width: 100%;
  height: 15px;
}

.author-name {
  margin: 10px;
}

.bio {
  margin: 20px;
}

.error-msg {
  color: var(--light-grey);
}

.btn {
  cursor: pointer;
  width: 200px;
  margin: 10px;
  color: var(--main-bg-color);
  font-size: 14px;
  background-color: var(--golden-yellow);
  background-image: linear-gradient(#fecc4c, #ffac33);
  border-color: var(--golden-yellow);
  border-width: 3px;
}
```

```js
const authorContainer = document.getElementById('author-container');
const loadMoreBtn = document.getElementById('load-more-btn');

let startingIndex = 0;
let endingIndex = 8;
let authorDataArr = [];

const initialFetch = async () => {
--fcc-editable-region--
  
  const res = await fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json');
  authorDataArr = await res.json();
  displayAuthors(authorDataArr.slice(startingIndex, endingIndex));
  .catch((err) => {
    authorContainer.innerHTML = '<p class="error-msg">There was an error loading the authors</p>';
  });
--fcc-editable-region--
}

const fetchMoreAuthors = () => {
  startingIndex += 8;
  endingIndex += 8;

  displayAuthors(authorDataArr.slice(startingIndex, endingIndex));
  if (authorDataArr.length <= endingIndex) {
    loadMoreBtn.disabled = true;
    loadMoreBtn.style.cursor = 'not-allowed';
    loadMoreBtn.textContent = 'No more data to load';
  }
};

const displayAuthors = (authors) => {
  authors.forEach(({ author, image, url, bio }, index) => {
    authorContainer.innerHTML += `
      <div id="${index}" class="user-card">
        <h2 class="author-name">${author}</h2>
        <img class="user-img" src="${image}" alt="${author} avatar" />
        <div class="purple-divider"></div>
        <p class="bio">${bio.length > 50 ? bio.slice(0, 50) + '...' : bio}</p>
        <a class="author-link" href="${url}" target="_blank">${author}'s author page</a>
      </div>
    `;
  });
};

initialFetch();
loadMoreBtn.addEventListener('click', fetchMoreAuthors);
```


# --solutions--

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>freeCodeCamp News Author Page</title>
    <link rel="stylesheet" href="./styles.css" />
  </head>
  <body>
    <h1 class="title">freeCodeCamp News Author Page</h1>

    <main>
      <div id="author-container"></div>
      <button class="btn" id="load-more-btn">Load More Authors</button>
    </main>

    <script src="./script.js"></script>
  </body>
</html>
```

```css
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  --main-bg-color: #1b1b32;
  --light-grey: #f5f6f7;
  --dark-purple: #5a01a7;
  --golden-yellow: #feac32;
}

body {
  background-color: var(--main-bg-color);
  text-align: center;
}

.title {
  color: var(--light-grey);
  margin: 20px 0;
}

#author-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.user-card {
  border-radius: 15px;
  width: 300px;
  height: 350px;
  background-color: var(--light-grey);
  margin: 20px;
}

.user-img {
  width: 150px;
  height: 150px;
  object-fit: cover;
}

.purple-divider {
  background-color: var(--dark-purple);
  width: 100%;
  height: 15px;
}

.author-name {
  margin: 10px;
}

.bio {
  margin: 20px;
}

.error-msg {
  color: var(--light-grey);
}

.btn {
  cursor: pointer;
  width: 200px;
  margin: 10px;
  color: var(--main-bg-color);
  font-size: 14px;
  background-color: var(--golden-yellow);
  background-image: linear-gradient(#fecc4c, #ffac33);
  border-color: var(--golden-yellow);
  border-width: 3px;
}
```

```js
const authorContainer = document.getElementById('author-container');
const loadMoreBtn = document.getElementById('load-more-btn');

let startingIndex = 0;
let endingIndex = 8;
let authorDataArr = [];

const initialFetch = async () => {
  try {
    const res = await fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json');
    authorDataArr = await res.json();
    displayAuthors(authorDataArr.slice(startingIndex, endingIndex));
  } catch (err) {
    authorContainer.innerHTML = '<p class="error-msg">There was an error loading the authors</p>';
  }
}

const fetchMoreAuthors = () => {
  startingIndex += 8;
  endingIndex += 8;

  displayAuthors(authorDataArr.slice(startingIndex, endingIndex));
  if (authorDataArr.length <= endingIndex) {
    loadMoreBtn.disabled = true;
    loadMoreBtn.style.cursor = 'not-allowed';
    loadMoreBtn.textContent = 'No more data to load';
  }
};

const displayAuthors = (authors) => {
  authors.forEach(({ author, image, url, bio }, index) => {
    authorContainer.innerHTML += `
      <div id="${index}" class="user-card">
        <h2 class="author-name">${author}</h2>
        <img class="user-img" src="${image}" alt="${author} avatar" />
        <div class="purple-divider"></div>
        <p class="bio">${bio.length > 50 ? bio.slice(0, 50) + '...' : bio}</p>
        <a class="author-link" href="${url}" target="_blank">${author}'s author page</a>
      </div>
    `;
  });
};

initialFetch();
loadMoreBtn.addEventListener('click', fetchMoreAuthors);
```
