DEV Community

mixbo
mixbo

Posted on

Use service object in nuxt.js

Alt Text

Nuxt.js awesome SSR framwork use in my team, we use axios lib to request http and deal with response.

Also we use Vuex to store state data between component and pages.

We just use service to wrap axios request, so that we can write logic more robust. let's show you some code

ApplicationService class

// ApplicationService.js

import extend from 'lodash/extend'
import { compact } from 'lodash'
import { environment } from '../config'

const querystring = require('querystring')

class ApplicationService {
  constructor(ctx) {
    this.cache = ctx.cache
    this.logger = ctx.app.$logger
    this.axios = ctx.$axios
  }
  get(path, params = {}, extraConf = {}) {
    return this.request(path, 'GET', params, extraConf)
  }

  post(path, data, extraConfig = {}) {
    return this.request(path, 'POST', data, extraConfig)
  }

  put(path, data, extraConf = {}) {
    return this.request(path, 'PUT', data, extraConf)
  }

  delete(path, data = {}, extraConf = {}) {
    return this.request(path, 'DELETE', data, extraConf)
  }

  extraResp(response) {
    const data = (response && response.data) || {}
    return (data && data.data) || { err: true, code: data.code, message: data.message }
  }

  async request(path, method = 'GET', paramsData = {}, extraConfig = {}) {
    const { axios } = this
    const config = extend({method,url: path,responseType: 'json'},extraConfig,)
    try {
      const response = await axios(config)
      return this.extraResp(response)
    } catch (err) {
      console.warn('application Service', err)
      return { err: true }
    }
  }
}

export default ApplicationService

Enter fullscreen mode Exit fullscreen mode

UserService.js

import get from 'lodash/get'
import ApplicationService from './ApplicationService'

export default class UserService extends ApplicationService {
  // fetch users list
  users() {
    return this.get('/users')
  }

  // find user by userId
  user(userId){
    return this.get(`/users/${userId}`)
  }
}

Enter fullscreen mode Exit fullscreen mode

Inject to nuxt.js global variable

// ~/plugins/service.js

import UserService from 'UserService.js'

export default (ctx, inject) => {
  ctx.userService = new UserService(ctx)
  inject('userService', ctx.userService)
}

// we can call userService 
this.$userService.users()
this.$userService.user(1)
Enter fullscreen mode Exit fullscreen mode

UserServiceTest.js

import service from 'UserService.js'

test('users', async () => {
  const data = [{name: 'foo', age: 23}]
  service.mockResponse({ data })
  const users = await service.users()
  service.expectCalledWith({ url: '/users' })
  expect(users).toEqual([{name: 'foo', age: 23}])
})
Enter fullscreen mode Exit fullscreen mode

OK, so far you can write independent UserServiceTest.js and test work on.

Do that you have benefit:

  • service object just care how to fetch resource from remote server
  • write more clean and independent test file
  • call service with nuxt global object context with this.$service.user

Hope it can help you :)

Top comments (2)

Collapse
 
amirhoseinbahrami profile image
AmirHoseinBahrami

How to do it in type script ?

Collapse
 
ihavecoke profile image
mixbo

You can just transform the js code to typescript that is all?