Skip to content

5. Async Data

Khriztian Moreno edited this page Nov 8, 2017 · 2 revisions

You may want to fetch data and render it on the server-side. Nuxt.js adds an asyncData method to let you handle async operations before setting the component data.

Dummy Gists

In our page index.vue we will add the script where we will work all our javascript code:

<script>
  const gistsLocal = [
    {
      'url': 'https://api.github.com/gists/51891107b240fbd61c3c3fd725a6bf4a',
      'commits_url': 'https://api.github.com/gists/51891107b240fbd61c3c3fd725a6bf4a/commits',
      'id': '51891107b240fbd61c3c3fd725a6bf4a',
      'git_pull_url': 'https://gist.github.com/51891107b240fbd61c3c3fd725a6bf4a.git',
      'git_push_url': 'https://gist.github.com/51891107b240fbd61c3c3fd725a6bf4a.git',
      'html_url': 'https://gist.github.com/51891107b240fbd61c3c3fd725a6bf4a',
      'files': {
        'talk-nodeJS-medellin.md': {
          'filename': 'talk-nodeJS-medellin.md',
          'type': 'text/plain',
          'language': 'Markdown',
          'raw_url': 'https://gist.githubusercontent.com/khriztianmoreno/51891107b240fbd61c3c3fd725a6bf4a/raw/fd1420ae3a3e352c23fd84090a891f9b84cdee09/talk-nodeJS-medellin.md',
          'size': 9082
        }
      },
      'public': true,
      'created_at': '2017-09-28T03:16:39Z',
      'updated_at': '2017-10-26T03:53:24Z',
      'description': 'Talk: Estructurando la base de nuestro proyecto',
      'comments': 0,
      'user': null,
      'comments_url': 'https://api.github.com/gists/51891107b240fbd61c3c3fd725a6bf4a/comments',
      'owner': {
        'login': 'khriztianmoreno',
        'id': 1481964,
        'avatar_url': 'https://avatars1.githubusercontent.com/u/1481964?v=4',
        'gravatar_id': '',
        'url': 'https://api.github.com/users/khriztianmoreno',
        'html_url': 'https://github.com/khriztianmoreno',
        'followers_url': 'https://api.github.com/users/khriztianmoreno/followers',
        'following_url': 'https://api.github.com/users/khriztianmoreno/following{/other_user}',
        'gists_url': 'https://api.github.com/users/khriztianmoreno/gists{/gist_id}',
        'starred_url': 'https://api.github.com/users/khriztianmoreno/starred{/owner}{/repo}',
        'subscriptions_url': 'https://api.github.com/users/khriztianmoreno/subscriptions',
        'organizations_url': 'https://api.github.com/users/khriztianmoreno/orgs',
        'repos_url': 'https://api.github.com/users/khriztianmoreno/repos',
        'events_url': 'https://api.github.com/users/khriztianmoreno/events{/privacy}',
        'received_events_url': 'https://api.github.com/users/khriztianmoreno/received_events',
        'type': 'User',
        'site_admin': false
      },
      'truncated': false
    },
    {
      'url': 'https://api.github.com/gists/08b5102c533d489d25db8e467b207648',
      'forks_url': 'https://api.github.com/gists/08b5102c533d489d25db8e467b207648/forks',
      'commits_url': 'https://api.github.com/gists/08b5102c533d489d25db8e467b207648/commits',
      'id': '08b5102c533d489d25db8e467b207648',
      'git_pull_url': 'https://gist.github.com/08b5102c533d489d25db8e467b207648.git',
      'git_push_url': 'https://gist.github.com/08b5102c533d489d25db8e467b207648.git',
      'html_url': 'https://gist.github.com/08b5102c533d489d25db8e467b207648',
      'files': {
        'GIF-Screencast-OSX.md': {
          'filename': 'GIF-Screencast-OSX.md',
          'type': 'text/plain',
          'language': 'Markdown',
          'raw_url': 'https://gist.githubusercontent.com/khriztianmoreno/08b5102c533d489d25db8e467b207648/raw/fa006ed2e0f785f778b58545861583bd0c4393c8/GIF-Screencast-OSX.md',
          'size': 2817
        },
        'Performance-vs-quality.md': {
          'filename': 'Performance-vs-quality.md',
          'type': 'text/plain',
          'language': 'Markdown',
          'raw_url': 'https://gist.githubusercontent.com/khriztianmoreno/08b5102c533d489d25db8e467b207648/raw/9868405d0b45a6e78774c7b2cab704464ddaeef7/Performance-vs-quality.md',
          'size': 3703
        }
      },
      'public': true,
      'created_at': '2017-09-08T17:00:06Z',
      'updated_at': '2017-09-08T17:00:06Z',
      'description': 'OS X Screencast to animated GIF',
      'comments': 0,
      'user': null,
      'comments_url': 'https://api.github.com/gists/08b5102c533d489d25db8e467b207648/comments',
      'owner': {
        'login': 'khriztianmoreno',
        'id': 1481964,
        'avatar_url': 'https://avatars1.githubusercontent.com/u/1481964?v=4',
        'gravatar_id': '',
        'url': 'https://api.github.com/users/khriztianmoreno',
        'html_url': 'https://github.com/khriztianmoreno',
        'followers_url': 'https://api.github.com/users/khriztianmoreno/followers',
        'following_url': 'https://api.github.com/users/khriztianmoreno/following{/other_user}',
        'gists_url': 'https://api.github.com/users/khriztianmoreno/gists{/gist_id}',
        'starred_url': 'https://api.github.com/users/khriztianmoreno/starred{/owner}{/repo}',
        'subscriptions_url': 'https://api.github.com/users/khriztianmoreno/subscriptions',
        'organizations_url': 'https://api.github.com/users/khriztianmoreno/orgs',
        'repos_url': 'https://api.github.com/users/khriztianmoreno/repos',
        'events_url': 'https://api.github.com/users/khriztianmoreno/events{/privacy}',
        'received_events_url': 'https://api.github.com/users/khriztianmoreno/received_events',
        'type': 'User',
        'site_admin': false
      },
      'truncated': false
    }
  ]
</script>

Method

Nuxt.js offers you different ways to use asyncData. Choose the one you're the most familiar with: Promise, async/await o callback

<script>
  // ... const gistsLocal

  export default {
    data () {
      return { gists: gistsLocal }
    },
    asyncData () {
      return gistsLocal
    }
  }
</script>

Refactor Page

We are going to make an improvement to our current main page to use a component that we can reuse later, that's why in the components folder we created the file GistArticle.vue with the following content:

<template>
  <article class="post post-large">
    <div v-if="gist">
      <div class="post-date">
        <span class="day">{{ gist.created_at | date('D') }}</span>
        <span class="month">{{ gist.created_at | date('MMM') }}</span>
      </div>
      <div class="post-content">
        <h2>
          <nuxt-link :to="{ path: '/post/'+ gist.id }">{{gist.description}}</nuxt-link>
        </h2>
        <!-- Content Raw -->
        <p>{{gist.description}}</p>
        <!-- /Content Raw -->
        <div class="post-meta">
          <span>
          <i class="fa fa-user"></i>
          By <a :href="gist.owner.html_url" target="_blank">{{ gist.owner.login }}</a>
          </span>
          <span>
          <i class="fa fa-comments"></i>
          <a :href="gist.comments_url" target="_blank">{{ gist.comments }} Comments</a>
          </span>
          <a :href="'/post/'+ gist.id +''" class="btn btn-xs btn-primary pull-right">Read more...</a>
        </div>
      </div>
    </div>
  </article>
</template>


<script>
  export default {
    props: ['gist']
  }
</script>

<style lang="scss" scoped>
  $primary-color: #41b883;
  $secundary-color: #35495f;
  $hover-color: #3c8070;

  .pagination {
    margin: -10px 0 20px;
  }

  .btn-primary {
    background-color: $primary-color;
    border-color: $primary-color;

    &:hover {
      background-color: $hover-color;
      border-color: $hover-color;
    }
  }

  article {
    border-bottom: 1px solid #DDD;
    margin-bottom: 50px;
    padding-bottom: 10px;

    &.post {
      h2 a {
        text-decoration: none;
      }
      .post-meta {
        font-size: 0.9em;
        margin-bottom: 7px;
        >span {
          display: inline-block;
          padding-right: 8px;
        }
        i {
          margin-right: 3px;
        }
      }
      .post-date {
        box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.1);
        float: left;
        margin-right: 10px;
        text-align: center;
        .month {
          background-color: $primary-color;
          border-radius: 0 0 2px 2px;
          box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.07) inset;
          color: #FFF;
          font-size: 0.9em;
          padding: 0 10px 2px;
        }
        .day {
          background: #F4F4F4;
          border-radius: 2px 2px 0 0;
          color: $primary-color;
          display: block;
          font-size: 16px;
          font-weight: 500;
          font-weight: bold;
          padding: 10px;
        }
      }
    }
    &.post-large {
      margin-left: 60px;
      h2 {
        margin-bottom: 5px;
      }
      .post-date {
        margin-left: -60px;
      }
    }
  }
</style>

And now our main page index.vue should be as follows:

<template>
  <section>
    <div class="main-container">
      <div class="blog-posts">
        <gist-article :key="item.id" v-for="(item, index) in gists" :gist="item" />
      </div>
    </div>
  </section>
</template>

<script>
  import GistArticle from '~/components/GistArticle.vue'

  const gistsLocal = [
    {
      'url': 'https://api.github.com/gists/51891107b240fbd61c3c3fd725a6bf4a',
      'commits_url': 'https://api.github.com/gists/51891107b240fbd61c3c3fd725a6bf4a/commits',
      'id': '51891107b240fbd61c3c3fd725a6bf4a',
      'git_pull_url': 'https://gist.github.com/51891107b240fbd61c3c3fd725a6bf4a.git',
      'git_push_url': 'https://gist.github.com/51891107b240fbd61c3c3fd725a6bf4a.git',
      'html_url': 'https://gist.github.com/51891107b240fbd61c3c3fd725a6bf4a',
      'files': {
        'talk-nodeJS-medellin.md': {
          'filename': 'talk-nodeJS-medellin.md',
          'type': 'text/plain',
          'language': 'Markdown',
          'raw_url': 'https://gist.githubusercontent.com/khriztianmoreno/51891107b240fbd61c3c3fd725a6bf4a/raw/fd1420ae3a3e352c23fd84090a891f9b84cdee09/talk-nodeJS-medellin.md',
          'size': 9082
        }
      },
      'public': true,
      'created_at': '2017-09-28T03:16:39Z',
      'updated_at': '2017-10-26T03:53:24Z',
      'description': 'Talk: Estructurando la base de nuestro proyecto',
      'comments': 0,
      'user': null,
      'comments_url': 'https://api.github.com/gists/51891107b240fbd61c3c3fd725a6bf4a/comments',
      'owner': {
        'login': 'khriztianmoreno',
        'id': 1481964,
        'avatar_url': 'https://avatars1.githubusercontent.com/u/1481964?v=4',
        'gravatar_id': '',
        'url': 'https://api.github.com/users/khriztianmoreno',
        'html_url': 'https://github.com/khriztianmoreno',
        'followers_url': 'https://api.github.com/users/khriztianmoreno/followers',
        'following_url': 'https://api.github.com/users/khriztianmoreno/following{/other_user}',
        'gists_url': 'https://api.github.com/users/khriztianmoreno/gists{/gist_id}',
        'starred_url': 'https://api.github.com/users/khriztianmoreno/starred{/owner}{/repo}',
        'subscriptions_url': 'https://api.github.com/users/khriztianmoreno/subscriptions',
        'organizations_url': 'https://api.github.com/users/khriztianmoreno/orgs',
        'repos_url': 'https://api.github.com/users/khriztianmoreno/repos',
        'events_url': 'https://api.github.com/users/khriztianmoreno/events{/privacy}',
        'received_events_url': 'https://api.github.com/users/khriztianmoreno/received_events',
        'type': 'User',
        'site_admin': false
      },
      'truncated': false
    },
    {
      'url': 'https://api.github.com/gists/08b5102c533d489d25db8e467b207648',
      'forks_url': 'https://api.github.com/gists/08b5102c533d489d25db8e467b207648/forks',
      'commits_url': 'https://api.github.com/gists/08b5102c533d489d25db8e467b207648/commits',
      'id': '08b5102c533d489d25db8e467b207648',
      'git_pull_url': 'https://gist.github.com/08b5102c533d489d25db8e467b207648.git',
      'git_push_url': 'https://gist.github.com/08b5102c533d489d25db8e467b207648.git',
      'html_url': 'https://gist.github.com/08b5102c533d489d25db8e467b207648',
      'files': {
        'GIF-Screencast-OSX.md': {
          'filename': 'GIF-Screencast-OSX.md',
          'type': 'text/plain',
          'language': 'Markdown',
          'raw_url': 'https://gist.githubusercontent.com/khriztianmoreno/08b5102c533d489d25db8e467b207648/raw/fa006ed2e0f785f778b58545861583bd0c4393c8/GIF-Screencast-OSX.md',
          'size': 2817
        },
        'Performance-vs-quality.md': {
          'filename': 'Performance-vs-quality.md',
          'type': 'text/plain',
          'language': 'Markdown',
          'raw_url': 'https://gist.githubusercontent.com/khriztianmoreno/08b5102c533d489d25db8e467b207648/raw/9868405d0b45a6e78774c7b2cab704464ddaeef7/Performance-vs-quality.md',
          'size': 3703
        }
      },
      'public': true,
      'created_at': '2017-09-08T17:00:06Z',
      'updated_at': '2017-09-08T17:00:06Z',
      'description': 'OS X Screencast to animated GIF',
      'comments': 0,
      'user': null,
      'comments_url': 'https://api.github.com/gists/08b5102c533d489d25db8e467b207648/comments',
      'owner': {
        'login': 'khriztianmoreno',
        'id': 1481964,
        'avatar_url': 'https://avatars1.githubusercontent.com/u/1481964?v=4',
        'gravatar_id': '',
        'url': 'https://api.github.com/users/khriztianmoreno',
        'html_url': 'https://github.com/khriztianmoreno',
        'followers_url': 'https://api.github.com/users/khriztianmoreno/followers',
        'following_url': 'https://api.github.com/users/khriztianmoreno/following{/other_user}',
        'gists_url': 'https://api.github.com/users/khriztianmoreno/gists{/gist_id}',
        'starred_url': 'https://api.github.com/users/khriztianmoreno/starred{/owner}{/repo}',
        'subscriptions_url': 'https://api.github.com/users/khriztianmoreno/subscriptions',
        'organizations_url': 'https://api.github.com/users/khriztianmoreno/orgs',
        'repos_url': 'https://api.github.com/users/khriztianmoreno/repos',
        'events_url': 'https://api.github.com/users/khriztianmoreno/events{/privacy}',
        'received_events_url': 'https://api.github.com/users/khriztianmoreno/received_events',
        'type': 'User',
        'site_admin': false
      },
      'truncated': false
    }
  ]

  export default {
    data () {
      return { gists: gistsLocal }
    },
    asyncData () {
      return gistsLocal
    },
    components: {
      GistArticle
    }
  }
</script>

<style>
  .main-container {
    align-items: center;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    min-height: 30vh;
  }
</style>

To see these steps complete, you can change to the 5-async-data branch in this repository.