Skip to content

14. مثال [nuxt-11]: سفارشی‌سازی تصویر بارگذاری

به طور پیش‌فرض، تصویر بارگذاری برای [nuxt] یک نوار پیشرفت است. مثال [nuxt-11] نشان می‌دهد که می‌توان آن را با تصویر بارگذاری دلخواه خود جایگزین کرد:

Image

مثال [nuxt-11] همچنین نشان می‌دهد که چگونه خطاهای بارگذاری را مدیریت کنید.

Image

نمونه [nuxt-11] در ابتدا با کپی کردن نمونه [nuxt-10] به دست می‌آید:

Image

در [1]، ما یک افزونه سمت کلاینت اضافه خواهیم کرد که برای مدیریت رویدادها بین اجزا طراحی شده است.

14.1. پلاگین [event-bus]

پلاگین [event-bus] هم توسط کلاینت و هم توسط سرور اجرا خواهد شد، اما خواهیم دید که در سمت سرور کار نمی‌کند. کد آن به شرح زیر است:


//ایجاد یک اتوبوس رویداد بین ویوها
import Vue from 'vue'
export default (context, inject) => {
  // اتوبوس رویداد
  const eventBus = new Vue()
  //تزریق یک تابع [eventBus] به زمینه
  inject('eventBus', () => eventBus)
}
  • خط ۵: اتوبوس رویداد یک نمونه از کلاس [Vue] است. این کلاس متدهای مدیریت رویدادها را فراهم می‌کند:
    • [$emit]: برای ایجاد یک رویداد؛
    • [$on]: برای گوش دادن به یک رویداد خاص؛

این اتوبوس رویداد تنها یک رویداد، [loading]، را مدیریت خواهد کرد که توسط صفحات برای شروع یا توقف انیمیشن در حین انتظار برای تکمیل یک تابع غیرهمزمان استفاده می‌شود؛

  • خط ۷: ما تابع [$eventBus] (آرگومان اول) را ایجاد می‌کنیم که وظیفه‌اش بازگرداندن شیء [eventBus] است که همین حالا ایجاد کرده‌ایم (آرگومان دوم). این تابع در زمینه تزریق می‌شود تا در اشیاء [context.app] و [this] در صفحات در دسترس باشد؛

14.2. قالب [default.vue]

قالب [default.vue] به شرح زیر تغییر می‌کند:


<template>
  <div class="container">
    <b-card>
      <!-- یک پیام -->
      <b-alert show variant="success" align="center">
        <h4>[nuxt-11] : personnalisation de l'attente, gestion des erreurs</h4>
      </b-alert>
      <!--نمای مسیریابی فعلی -->
      <nuxt />
      <!--در حال بارگذاری -->
      <b-alert v-if="showLoading" show variant="light">
        <strong>Requête au serveur de données en cours...</strong>
        <div class="spinner-border ml-auto" role="status" aria-hidden="true"></div>
      </b-alert>
      <!-- خطای بارگذاری -->
      <b-alert v-if="showErrorLoading" show variant="danger">
        <strong>La requête au serveur de données a échoué : {{ errorLoadingMessage }}</strong>
      </b-alert>
    </b-card>
  </div>
</template>

<script>
/*eslint-disable no-console */
export default {
  name: 'App',
  data() {
    return {
      showLoading: false,
      showErrorLoading: false
    }
  },
  // چرخهٔ عمر
  beforeCreate() {
    console.log('[default beforeCreate]')
  },
  created() {
    console.log('[default created]')
    // منتظر رویداد [loading]
    this.$eventBus().$on('loading', this.mShowLoading)
    // و همچنین رویداد [errorLoadingMessage]
    this.$eventBus().$on('errorLoading', this.mShowErrorLoading)
  },
  beforeMount() {
    console.log('[default beforeMount]')
  },
  mounted() {
    console.log('[default mounted]')
  },
  methods: {
    // مدیریت بار
    mShowLoading(value) {
      console.log('[default mShowLoading], showLoading=', value)
      this.showLoading = value
    },
    // خطای بارگذاری
    mShowErrorLoading(value, errorLoadingMessage) {
      console.log('[default mShowErrorLoading], showErrorLoading=', value, 'errorLoadingMessage=', errorLoadingMessage)
      this.showErrorLoading = value
      this.errorLoadingMessage = errorLoadingMessage
    }
  }
}
</script>
  • خطوط ۱۱–۱۴: انیمیشن بارگذاری. این تنها در صورتی نمایش داده می‌شود که ویژگی [showLoading] (خط ۲۹) درست باشد؛
  • خطوط ۱۶–۱۸: پیام خطای بارگذاری. این پیام تنها در صورتی نمایش داده می‌شود که ویژگی [showErrorLoading] (خط ۳۰) مقدار true داشته باشد؛
  • خطوط ۲۹–۳۰: هنگامی که کامپوننت برای اولین بار بارگذاری می‌شود، انیمیشن بارگذاری و پیام خطا پنهان می‌شوند؛
  • خطوط ۳۷–۴۳: هنگام ایجاد، صفحه به رویداد [loading] (اولین آرگومان) روی باس رویداد ایجاد شده توسط افزونه گوش فرا می‌دهد. پس از دریافت آن، متد [mShowLoading] را در خطوط ۵۲–۵۵ (دومین آرگومان) اجرا می‌کند؛
  • خطوط ۵۲–۵۵: مقدار دریافتی متد [mShowLoading] یک مقدار بولی (true یا false) خواهد بود. این مقدار برای نمایش یا پنهان کردن پیام بارگذاری استفاده می‌شود؛
  • خطوط ۴۱–۴۲: وقتی صفحه ایجاد می‌شود، به رویداد [errorLoading] (آرگومان اول) روی باس رویداد ایجادشده توسط افزونه گوش می‌دهد. پس از دریافت آن، متد [mShowErrorLoading] را در خطوط ۵۷–۶۱ (آرگومان دوم) اجرا می‌کند؛
  • خط ۵۷: متد [mShowErrorLoading] دو آرگومان می‌گیرد:
    • آرگومان اول یک مقدار بولی (true/false) است که برای نمایش یا پنهان کردن پیام خطا استفاده می‌شود؛
    • آرگومان دوم تنها در صورتی وجود دارد که خطایی رخ داده باشد. این آرگومان پیام خطایی را که باید نمایش داده شود، نشان می‌دهد؛
  • لاگ‌های خطوط 53 و 58 نشان می‌دهند که متدهای [showLoading] و [showErrorLoading] در سمت سرور اجرا نمی‌شوند؛

14.3. صفحه [page1]

کد صفحه [page1] به شرح زیر تغییر می‌کند:


<!-- نما شماره ۱ -->
<template>
  <Layout :left="true" :right="true">
    <!-- ناوبری -->
    <Navigation slot="left" />
    <!-- پیام-->
    <b-alert slot="right" show variant="primary"> Page 1 -- result={{ result }} </b-alert>
  </Layout>
</template>

<script>
/* eslint-disable no-console */
/*eslint-disable nuxt/no-timing-in-fetch-data */

import Navigation from '@/components/navigation'
import Layout from '@/components/layout'

export default {
  name: 'Page1',
  // کامپوننت‌های استفاده شده
  components: {
    Layout,
    Navigation
  },
  // داده‌های ناهمزمان
  asyncData(context) {
    // لاگ
    console.log('[page1 asyncData started]')
    // شروع انتظار
    context.app.$eventBus().$emit('loading', true)
    // بدون خطا
    context.app.$eventBus().$emit('errorLoading', false)
    // یک promise بازگردانده می‌شود
    return new Promise(function(resolve, reject) {
      //شبیه‌سازی یک تابع ناهمزمان
      setTimeout(function() {
        //پایان انتظار
        context.app.$eventBus().$emit('loading', false)
        // لاگ
        console.log('[page1 asyncData finished]')
        // بازگرداندن نتیجهٔ ناهمزمان – یک عدد تصادفی در اینجا
        resolve({ result: Math.floor(Math.random() * Math.floor(100)) })
      }, 5000)
    })
  },

  //چرخهٔ زندگی
  beforeCreate() {
    console.log('[page1 beforeCreate]')
  },
  created() {
    console.log('[page1 created]')
  },
  beforeMount() {
    console.log('[page1 beforeMount]')
  },
  mounted() {
    console.log('[page1 mounted]')
  }
}
</script>
  • تغییرات در تابع [asyncData] در خطوط 26 تا 47 رخ می‌دهد؛
  • خطوط ۲۹–۳۰: قبل از شروع تابع غیرهمزمان، رویداد [loading] برای صفحات دیگر برنامه فعال می‌شود. شایان ذکر است که در [asyncData]، هیچ دسترسی به شیء [this] وجود ندارد، زیرا هنوز ایجاد نشده است. بنابراین از کانتکستی که به عنوان آرگومان به تابع [asyncData] (خط 26) ارسال شده است، استفاده می‌شود؛
  • خط ۳۰: از باس رویداد برای نشان دادن اینکه بارگذاری در شرف شروع است استفاده می‌شود؛
  • خط ۳۸: از باس رویداد برای نشان دادن اتمام بارگذاری استفاده می‌شود؛

توجه: در زمان اجرا، هنگامی که صفحه [page1] از سرور درخواست می‌شود، تصویر بارگذاری نمایش داده نمی‌شود. لاگ‌ها نشان می‌دهند که در سمت سرور، متد [default.mShowLoading] فراخوانی نمی‌شود. در هر صورت، نمایش تصویر بارگذاری زمانی که صفحه از سرور درخواست می‌شود، بی‌معنی است. سرور تنها پس از اتمام تابع [asyncData]، صفحه را برای مرورگر کلاینت ارسال می‌کند. بنابراین تصویر بارگذاری غیرضروری است. این وضعیت برای تمام صفحات اپلیکیشن که مستقیماً از سرور درخواست می‌شوند نیز صادق است.

14.4. صفحه [index]

کد صفحه [index] به شرح زیر است:


<!--صفحهٔ اصلی -->
<template>
  <Layout :left="true" :right="true">
    <!-- ناوبری -->
    <Navigation slot="left" />
    <!-- پیام-->
    <b-alert slot="right" show variant="warning">
      Home
    </b-alert>
  </Layout>
</template>

<script>
/* eslint-disable no-undef */
/* eslint-disable no-console */
/* eslint-disable nuxt/no-env-in-hooks */
/*eslint-disable nuxt/no-timing-in-fetch-data */

import Navigation from '@/components/navigation'
import Layout from '@/components/layout'

export default {
  name: 'Home',
  // کامپوننت‌های استفاده شده
  components: {
    Layout,
    Navigation
  },
  // داده‌های ناهمزمان
  asyncData(context) {
    // لاگ
    console.log('[page1 asyncData started]')
    // شروع انتظار
    context.app.$eventBus().$emit('loading', true)
    // بدون خطا
    context.app.$eventBus().$emit('errorLoading', false)
    //یک promise بازگردانده می‌شود
    return new Promise(function(resolve, reject) {
      //شبیه‌سازی یک تابع ناهمزمان
      setTimeout(function() {
        // پایان انتظار
        context.app.$eventBus().$emit('loading', false)
        // لاگ
        console.log('[page1 asyncData finished]')
        //خطا را برمی‌گرداند
        reject(new Error("le serveur n'a pas répondu assez vite"))
      }, 5000)
    }).catch((e) => context.error({ statusCode: 500, message: e.message }))
  },
  //چرخهٔ زندگی
  beforeCreate() {
    console.log('[home beforeCreate]')
  },
  created() {
    console.log('[home created]')
  },
  beforeMount() {
    console.log('[home beforeMount]')
  },
  mounted() {
    console.log('[home mounted]')
    // بدون خطا
    this.$eventBus().$emit('errorLoading', false)
  }
}
</script>
  • خطوط ۳۰–۴۹: تابع [asyncData] با تابع صفحه [page1] یکسان است، با این تفاوت جزئی که در خط ۴۶، تابع غیرهمزمان در صورت خطا (با استفاده از متد [reject]) خاتمه می‌یابد؛
  • خط ۴۶: پارامتر تابع [reject] یک نمونه از کلاس [Error] است. پارامتر سازنده [Error] پیام خطا است؛
  • خط ۴۸: این خطا توسط متد [catch] از کلاس [Promise] که خطا را به عنوان پارامتر دریافت می‌کند، مهار می‌شود. سپس از تابع [context.error] برای گزارش خطا استفاده می‌شود. پارامتر تابع [context.error] در این مورد یک شیء با دو ویژگی است:
    • [statusCode]: یک کد خطا HTTP;
    • [message]: یک پیام خطا؛

چه [asyncData] توسط کلاینت اجرا شود یا سرور، در صورت رخ دادن خطا [context.error]، [nuxt] صفحه [layouts / error.vue] را نمایش می‌دهد:

Image

اگرچه این یک صفحه است، صفحه [error.vue] در پوشه [layouts] جستجو می‌شود (شاید برای جلوگیری از گنجانده شدن آن در مسیرهای برنامه؟). در اینجا، صفحه [error.vue] به شرح زیر است:


<!--HTML تعریف نما -->
<template>
  <!-- قالب‌بندی -->
  <Layout :left="true" :right="true">
    <!-- هشدار در ستون سمت راست -->
    <template slot="right">
      <!-- پیام روی پس‌زمینه زرد -->
      <b-alert show variant="danger" align="center">
        <h4>L'erreur suivante s'est produite : {{ JSON.stringify(error) }}</h4>
      </b-alert>
    </template>
    <!-- منوی ناوبری در ستون سمت چپ -->
    <Navigation slot="left" />
  </Layout>
</template>

<script>
/*eslint-disable no-undef */
/* eslint-disable no-console */
/*eslint-disable nuxt/no-env-in-hooks */

import Layout from '@/components/layout'
import Navigation from '@/components/navigation'

export default {
  name: 'Error',
  // کامپوننت‌های استفاده شده
  components: {
    Layout,
    Navigation
  },
  // خصلت [props]
  props: { error: { type: Object, default: () => 'waiting ...' } },
  // چرخهٔ عمر
  beforeCreate() {
    // کلاینت و سرور
    console.log('[error beforeCreate]')
  },
  created() {
    // کلاینت و سرور
    console.log('[error created, error=]', this.error)
  },
  beforeMount() {
    //فقط کلاینت
    console.log('[error beforeMount]')
  },
  mounted() {
    //فقط کلاینت
    console.log('[error mounted]')
  }
}
</script>

هنگامی که [nuxt] صفحه [error.vue] را نمایش می‌دهد، خطایی را که رخ داده (خط ۳۳) به عنوان ویژگی [props] به آن منتقل می‌کند. اگر خطا توسط [context.error(objet1)] ایجاد شده باشد، ویژگی [props] صفحه [error.vue] مقدار [objet1] را خواهد داشت. مستندات [nuxt] بیان می‌کند که [objet1] باید حداقل ویژگی‌های [statusCode, message] را داشته باشد. خط ۹ رشته jSON را از شیء دریافتی [objet1] نمایش می‌دهد.

14.5. صفحه [page2]

صفحه [page2] روش دیگری برای رسیدگی به خطا نشان می‌دهد:

  • در [page1]، خطا در یک صفحهٔ جداگانه، [error.vue]، نمایش داده می‌شود؛
  • در [page2]، خطا بر روی صفحه‌ای که باعث خطا شده است، یعنی [page2]، نمایش داده خواهد شد؛

کد برای [page2] به شرح زیر است:


<!-- نما شمارهٔ ۲ -->
<template>
  <Layout :left="true" :right="true">
    <!-- ناوبری -->
    <Navigation slot="left" />
    <!-- پیام -->
    <b-alert slot="right" show variant="secondary">
      Page 2
    </b-alert>
  </Layout>
</template>

<script>
/*eslint-disable no-console */
/*eslint-disable nuxt/no-timing-in-fetch-data */

import Navigation from '@/components/navigation'
import Layout from '@/components/layout'

export default {
  name: 'Page2',
  // کامپوننت‌های استفاده شده
  components: {
    Layout,
    Navigation
  },
  // داده‌های ناهمزمان
  asyncData(context) {
    // لاگ
    console.log('[page2 asyncData started]')
    // شروع انتظار
    context.app.$eventBus().$emit('loading', true)
    // بدون خطا
    context.app.$eventBus().$emit('errorLoading', false)
    // یک promise بازگردانده می‌شود
    return new Promise(function(resolve, reject) {
      //شبیه‌سازی یک تابع ناهمزمان
      setTimeout(function() {
        //پایان انتظار
        context.app.$eventBus().$emit('loading', false)
        //تولید یک خطای دلخواه
        const errorLoadingMessage = "le serveur n'a pas répondu assez vite"
        // با موفقیت تکمیل شد
        resolve({ showErrorLoading: true, errorLoadingMessage })
        // لاگ
        console.log('[page2 asyncData finished]')
      }, 5000)
    })
  },
  //چرخه عمر
  beforeCreate() {
    console.log('[page2 beforeCreate]')
  },
  created() {
    console.log('[page2 created]')
  },
  beforeMount() {
    console.log('[page2 beforeMount]')
  },
  mounted() {
    console.log('[page2 mounted]')
    // کلاینت
    if (this.showErrorLoading) {
      console.log('[page2 mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
  }
}
</script>

بار دیگر، ما یک تابع [asyncData] را در کد صفحه قرار می‌دهیم و مانند [index]، [page2] یک خطا تولید خواهد کرد که این بار آن را به شیوه‌ای متفاوت مدیریت خواهیم کرد.

  • خط ۴۴: هم سرور و هم کلاینت با بازگرداندن نتیجه [{ showErrorLoading: true, errorLoadingMessage }]، پراموس را با موفقیت حل می‌کنند. ما می‌دانیم که این امر منجر به گنجانده شدن ویژگی‌های [showerrorLoading, errorLoadingMessage] در ویژگی‌های [data] صفحه می‌شود، و اینکه کلاینت این ویژگی‌ها را دریافت خواهد کرد؛
  • خطوط ۶۰–۶۷: می‌دانیم که تابع [mounted] تنها توسط کلاینت اجرا می‌شود؛
  • خط ۶۳: کلاینت بررسی می‌کند که آیا ویژگی [showErrorLoading] (توسط سرور یا کلاینت، بسته به مورد) تنظیم شده است یا خیر. در این صورت، رویداد [‘errorLoading’] (خط ۶۵) را فعال می‌کند تا صفحه [default] پیام خطای [this.errorLoadingMessage] را نمایش دهد. در نهایت، سرور صفحه‌ای را بدون نمایش هیچ پیام خطایی ارسال می‌کند. پیام خطا در لحظه آخر توسط کلاینت زمانی که صفحه «بارگذاری» می‌شود، نمایش داده می‌شود؛

14.6. Exécution

14.6.1. [nuxt.config]

فایل اجرایی [nuxt.config.js] به شرح زیر است:


export default {
  mode: 'universal',
  /*
   ** Headers of the page
   */
  head: {
    title: 'Introduction à [nuxt.js]',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      {
        hid: 'description',
        name: 'description',
        content: 'ssr routing loading asyncdata middleware plugins store'
      }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
  },
  /*
   ** Customize the progress-bar color
   */
  loading: false,

  /*
   ** Global CSS
   */
  css: [],
  /*
   ** Plugins to load before mounting the App
   */
  plugins: [{ src: '@/plugins/event-bus' }],
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    // مستندات: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Doc: https://bootstrap-vue.js.org
    'bootstrap-vue/nuxt',
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios'
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {},
  /*
   ** Build configuration
   */
  build: {
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {}
  },
  // پوشه کد منبع
  srcDir: 'nuxt-11',
  // روتر
  router: {
    // ریشهٔ برنامه
    base: '/nuxt-11/'
  },
  // سرور
  server: {
    // پورت سرویس، به‌صورت پیش‌فرض 3000
    port: 81,
    // آدرس‌های شبکه گوش‌داده‌شده، پیش‌فرض localhost: 127.0.0.1
    // 0.0.0.0 = تمام آدرس‌های شبکه روی دستگاه
    host: 'localhost'
  }
}
  • خط ۲۲: ویژگی [loading] روی [false] تنظیم می‌شود تا [nuxt] از تصویر بارگذاری پیش‌فرض خود استفاده نکند؛
  • خط ۳۱: پلاگینی که اتوبوس رویداد را تعریف می‌کند؛

14.6.2. L، صفحه‌ای [index] که توسط سرور اجرا می‌شود

بیایید صفحه [index] را از سرور درخواست کنیم (ما URL [http://localhost:81/nuxt-11/] را به‌صورت دستی تایپ می‌کنیم). صفحه‌ای که توسط مرورگر کلاینت نمایش داده می‌شود به شرح زیر است:

Image

لاگ‌ها به شرح زیر است:

Image

  • در [3]، می‌بینیم که سرور صفحه [error.vue] را ارسال می‌کند؛
  • در [4]، می‌بینیم که کلاینت نیز صفحه [error] را با همان خطای سمت سرور نمایش می‌دهد؛
  • مشاهده می‌شود که متد [mShowLoading] در صفحه [default] در سمت سرور فراخوانی نشده است، هرچند که صفحه [index] یک وقفه (wait) را فعال کرده بود. این متد هنگام دریافت یک رویداد فراخوانی می‌شود و واضح است که رسیدگی به رویداد در سمت سرور پیاده‌سازی نشده است؛

بیایید کد منبع صفحه‌ای را که توسط مرورگر کلاینت دریافت شده است، بررسی کنیم:


<!doctype html>
<html data-n-head-ssr>
<head>
  <title>Introduction à [nuxt.js]</title>
  <meta data-n-head="ssr" charset="utf-8">
  <meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
  <meta data-n-head="ssr" data-hid="description" name="description" content="ssr routing loading asyncdata middleware plugins store">
  <link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
  <base href="/nuxt-11/">
  <link rel="preload" href="/nuxt-11/_nuxt/runtime.js" as="script">
  <link rel="preload" href="/nuxt-11/_nuxt/commons.app.js" as="script">
  <link rel="preload" href="/nuxt-11/_nuxt/vendors.app.js" as="script">
  <link rel="preload" href="/nuxt-11/_nuxt/app.js" as="script">
  ...
</head>
<body>
  <div data-server-rendered="true" id="__nuxt">
    <div id="__layout">
      <div class="container">
        <div class="card">
          <div class="card-body">
            <div role="alert" aria-live="polite" aria-atomic="true" align="center" class="alert alert-success">
            <h4>[nuxt-11] : personnalisation de l'attente, gestion des erreurs</h4>
              </div>
            <div>
              <div class="row">
                <div class="col-2">
                  <ul class="nav flex-column">
                    <li class="nav-item">
                      <a href="/nuxt-11/" target="_self" class="nav-link active nuxt-link-active">
                        Home
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-11/page1" target="_self" class="nav-link">
                        Page 1
                      </a>
                    </li>
                    <li class="nav-item">
                      <a href="/nuxt-11/page2" target="_self" class="nav-link">
                        Page 2
                      </a>
                    </li>
                  </ul>
                </div> <div class="col-10"><div role="alert" aria-live="polite" aria-atomic="true" align="center" class="alert alert-danger">
                <h4>L'erreur suivante s'est produite : {&quot;statusCode&quot;:500,&quot;message&quot;:&quot;le serveur n'a pas répondu assez vite&quot;}</h4>
                    </div>
                </div>
              </div>
            </div>  
          </div>
        </div>
      </div>
    </div>
  </div>
  <script>window.__NUXT__ = (function (a, b, c, d) {
  d.statusCode = 500; d.message = "le serveur n'a pas répondu assez vite";
  return {
    layout: "default", data: [d], error: d, serverRendered: true,
    logs: [
      { date: new Date(1575047424168), args: ["[event-bus créé]"], type: a, level: b, tag: c },
      { date: new Date(1575047424175), args: ["[page1 asyncData started]"], type: a, level: b, tag: c },
      { date: new Date(1575047429455), args: ["[page1 asyncData finished]"], type: a, level: b, tag: c },
      { date: new Date(1575047429515), args: ["[default beforeCreate]"], type: a, level: b, tag: c },
      { date: new Date(1575047429675), args: ["[default created]"], type: a, level: b, tag: c },
      { date: new Date(1575047430157), args: ["[error beforeCreate]"], type: a, level: b, tag: c },
      { date: new Date(1575047430246), args: ["[error created, error=]", "{ statusCode: 500,\n  message: 'le serveur n\\'a pas répondu assez vite' }"], type: a, level: b, tag: c }]
  }
    }("log", 2, "", {}));</script>
  <script src="/nuxt-11/_nuxt/runtime.js" defer></script>
  <script src="/nuxt-11/_nuxt/commons.app.js" defer></script>
  <script src="/nuxt-11/_nuxt/vendors.app.js" defer></script>
  <script src="/nuxt-11/_nuxt/app.js" defer></script>
</body>
</html>
  • خط ۵۷: می‌بینیم که سرور یک شیء [d] را ارسال کرده است که نمایانگر خطایی است که در سمت سرور رخ داده است؛
  • خط ۵۹: می‌توانیم یک ویژگی [error] را ببینیم که مقدار آن شیء [d] است. ممکن است حضور ویژگی [error] در صفحه‌ای که توسط سرور ارسال شده است، باعث شود اسکریپت‌های سمت کلاینت صفحه [error.vue] را با خطای [error] نمایش دهند؛

14.6.3. صفحه [page1] که توسط سرور اجرا می‌شود

ما به‌صورت دستی URL [http://localhost:81/nuxt-11/page1] را وارد می‌کنیم. پس از ۵ ثانیه، مرورگر صفحه زیر را نمایش می‌دهد:

Image

لاگ‌های نمایش‌داده‌شده به شرح زیر است:

Image

  • در [1]، لاگ‌های سرور. مشاهده می‌شود که متد [mShowLoading] در صفحه [default] فراخوانی نشده است؛
  • در [2]، لاگ‌های کلاینت؛

14.6.4. صفحه [page2] که توسط سرور اجرا شده است

ما به صورت دستی URL [http://localhost:81/nuxt-11/page2] را وارد می‌کنیم. پس از ۵ ثانیه، مرورگر صفحه زیر را نمایش می‌دهد:

Image

بیایید لاگ‌های نمایش‌داده‌شده در مرورگر را بررسی کنیم:

Image

  • در [1]، لاگ‌های سرور. به یاد داشته باشید که سرور ویژگی‌های [showErrorLoading, errorLoadingMessage] را در صفحه‌ای که برای مرورگر کلاینت ارسال کرده بود، گنجانده بود. ما می‌دانیم که این ویژگی‌ها سپس در [data] صفحه نمایش‌داده‌شده توسط کلاینت گنجانده خواهند شد
  • در [3]، هنگامی که صفحه [page2] بارگذاری می‌شود، ویژگی [showErrorLoading] را که به مقدار true تنظیم شده است، پیدا می‌کند. سپس یک رویداد را به صفحه [default] ارسال می‌کند تا پیام خطای ارسال‌شده توسط سرور [4] را نمایش دهد؛

14.6.5. صفحه [index] که توسط کلاینت اجرا می‌شود

اکنون از لینک‌های ناوبری برای نمایش سه صفحه استفاده می‌کنیم. تمام صفحاتی که توسط کلاینت نمایش داده می‌شوند، دقیقاً مشابه صفحاتی هستند که توسط سرور نمایش داده می‌شوند. تنها تفاوت این است که تصویر شمارش معکوس ۵ ثانیه‌ای هر بار نمایش داده می‌شود.

ما با صفحه [index] شروع می‌کنیم. سپس تصویر بارگذاری نمایش داده می‌شود:

Image

سپس، پس از ۵ ثانیه، صفحه زیر ظاهر می‌شود:

Image

بنابراین صفحه نهایی با صفحه‌ای که در سمت سرور تولید می‌شود یکسان است.

Image

بیایید تابع [asyncData] را از صفحه [index] به یاد آوریم:


asyncData(context) {
    // لاگ
    console.log('[page1 asyncData started]')
    // شروع انتظار
    context.app.$eventBus().$emit('loading', true)
    // بدون خطا
    context.app.$eventBus().$emit('errorLoading', false)
    // یک promise بازگردانده می‌شود
    return new Promise(function(resolve, reject) {
      // شبیه‌سازی یک تابع ناهمزمان
      setTimeout(function() {
        // پایان انتظار
        context.app.$eventBus().$emit('loading', false)
        // لاگ
        console.log('[page1 asyncData finished]')
        //خطا را برمی‌گرداند
        reject(new Error("le serveur n'a pas répondu assez vite"))
      }, 5000)
    }).catch((e) => context.error({ statusCode: 500, message: e.message }))
}

لاگ‌های کلاینت به شرح زیر است:

Image

  • در [1]، تابع [asyncData] شروع می‌شود؛
  • در [2]، تصویر بارگذاری نمایش داده می‌شود؛
  • در [2-3]، می‌توانیم ببینیم که صفحه [default] رویدادهای [loading, true]، [2] و [errorLoading, false] را که توسط تابع [asyncData] در صفحه QZ ارسال شده است، دریافت کرده استXW2HTMLP001409ZQX (خطوط ۵ و ۷)؛
  • در [4]، پایان انتظار. صفحه [default] رویداد [loading, false] را که توسط صفحه [index] ارسال شده است، دریافت کرد (خط ۱۳);
  • در [5]، تابع [asyncData] کار خود را به پایان رسانده است؛
  • چون تابع [asyncData] خطایی را در [context.error] (خط ۱۹) ایجاد کرد، صفحه [error] به عنوان [6] نمایش داده می‌شود؛

14.6.6. صفحه [page1] که توسط کلاینت اجرا شد

پس از ۵ ثانیه انتظار، کلاینت صفحه زیر را نمایش می‌دهد:

Image

بیایید کد تابع [asyncData] را از [page1] به یاد آوریم:


asyncData(context) {
    // لاگ
    console.log('[page1 asyncData started]')
    // شروع انتظار
    context.app.$eventBus().$emit('loading', true)
    // بدون خطا
    context.app.$eventBus().$emit('errorLoading', false)
    // یک وعده را بازمی‌گرداند
    return new Promise(function(resolve, reject) {
      // شبیه‌سازی یک تابع ناهمزمان
      setTimeout(function() {
        //پایان انتظار
        context.app.$eventBus().$emit('loading', false)
        // لاگ
        console.log('[page1 asyncData finished]')
        // بازگرداندن نتیجهٔ ناهمزمان – یک عدد تصادفی در اینجا
        resolve({ result: Math.floor(Math.random() * Math.floor(100)) })
      }, 5000)
    })
},

لاگ‌ها به شرح زیر است:

Image

14.6.7. صفحه [page2] که توسط کلاینت اجرا شد

پس از ۵ ثانیه تأخیر، کلاینت صفحه زیر را نمایش می‌دهد:

Image

بیایید کد توابع [asyncData] و [mounted] را از [page2] به یاد آوریم:


asyncData(context) {
    // لاگ
    console.log('[page2 asyncData started]')
    // آغاز انتظار
    context.app.$eventBus().$emit('loading', true)
    // بدون خطا
    context.app.$eventBus().$emit('errorLoading', false)
    //یک promise بازمی‌گرداند
    return new Promise(function(resolve, reject) {
      //شبیه‌سازی یک تابع ناهمزمان
      setTimeout(function() {
        //پایان انتظار
        context.app.$eventBus().$emit('loading', false)
        //تولید یک خطای دلخواه
        const errorLoadingMessage = "le serveur n'a pas répondu assez vite"
        // با موفقیت تکمیل شد
        resolve({ showErrorLoading: true, errorLoadingMessage })
        // لاگ
        console.log('[page2 asyncData finished]')
      }, 5000)
    })
  }

mounted() {
    console.log('[page2 mounted]')
    // کلاینت
    if (this.showErrorLoading) {
      console.log('[page2 mounted, showErrorLoading=true]')
      this.$eventBus().$emit('errorLoading', true, this.errorLoadingMessage)
    }
}

لاگ‌ها به شرح زیر است:

Image

  • در [1]، صفحه [default] رویداد [showErrorLoading, true] را که توسط [page2] (خط ۲۹) ارسال شده است، دریافت می‌کند، که به آن دستور می‌دهد پیام خطا را نمایش دهد؛