<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Blind Kai</title>
    <description>The latest articles on DEV Community by Blind Kai (@blindkai).</description>
    <link>https://dev.to/blindkai</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F664386%2F8a64d10e-cd6f-4695-a307-f5db47694fb9.jpeg</url>
      <title>DEV Community: Blind Kai</title>
      <link>https://dev.to/blindkai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/blindkai"/>
    <language>en</language>
    <item>
      <title>Backend: Layered Architecture</title>
      <dc:creator>Blind Kai</dc:creator>
      <pubDate>Sun, 23 Jan 2022 10:04:45 +0000</pubDate>
      <link>https://dev.to/blindkai/backend-layered-architecture-514h</link>
      <guid>https://dev.to/blindkai/backend-layered-architecture-514h</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;Choosing the correct architecture for your backend application is an important decision because you will get the most of it in a long shot. This article is written to give Backend Developers an understanding of how to structure the code in order to make it properly incapsulated correspondingly to its purpose. Properly structured code that follows the same rules for each inner domain is easier to be read and maintain for you and other developers that would work with it. Better code you write at the start - less pain you get later when requirements will change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considering Layered Architecture
&lt;/h2&gt;

&lt;p&gt;When developers work in the backend, they've mostly worked with data and business logic around that data. No matter if you're dealing with API or if it's CLI - you need to structure your code properly.&lt;/p&gt;

&lt;p&gt;Layered Architecture is a great example of lightweight architecture which is not overwhelmed with redundant abstractions, contracts or boilerplate code.&lt;/p&gt;

&lt;p&gt;In order to implement this architecture correctly, you just need to place your code in a place according to its properties and purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  General schema
&lt;/h2&gt;

&lt;p&gt;For example, we need to design REST API architecture. If you're interested in reading more about REST API design, please check &lt;a href="https://dev.to/blindkai/rest-api-design-27j9"&gt;this link&lt;/a&gt;.&lt;br&gt;
The general schema of layers is shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwuk9zhfszle8qa4jfzof.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwuk9zhfszle8qa4jfzof.jpg" alt="General schema for layered architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we have three layers, let's discuss them in detail:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Controller layer&lt;/strong&gt;: Controllers themselves should only be responsible for work delegation. They should not contain any logic or direct data manipulation. The main purpose of a controller is to get the request, then pass it to the service that will process it and then return the response that is given from the service. See controllers like a manager for requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service layer&lt;/strong&gt;: Generally services contain information that is related to their domain. For example, if we have "Mail Service" we expect that sending/receiving emails happens there like in a real life. The same is fair for the codebase. Services (and their methods) handle the business logic which means that they are responsible for transforming data, performing additional actions &lt;em&gt;(like asking the repository for additional data or another service for processing some logic for it)&lt;/em&gt;. So if we need to send a mail, the service is responsible for getting the data as parameters, formatting them into the mail itself and sending it thru an external service or saving it thru the repository if it's an internal functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repository layer&lt;/strong&gt;: If there is code that somehow works with the database here is the place for this code to live. No matter if we're fetching the data from the DB or saving/modifying objects, it's the place where SQL queries or ORM operations should be placed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Detailed schema
&lt;/h2&gt;

&lt;p&gt;Let's discuss a few workflows to have a better understanding of how things could work if we're building the REST API for some "Shop orders" domains.&lt;br&gt;
Below you can see a few cases for writing domain code that follows the architecture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fof739v9cu7namgc9m2am.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fof739v9cu7namgc9m2am.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario A: User creates order
&lt;/h3&gt;

&lt;p&gt;For example, we have a user that wants to create a new order. The request comes into the controller, the request is validated so we ensure that we're working with valid parameters.&lt;br&gt;
Let's assume that the user also had discounts so we need to apply them in order to get the final price. For example, we have the service &lt;code&gt;UserOrderService&lt;/code&gt; which has the method &lt;code&gt;createOrder(user, order)&lt;/code&gt;. Within this method, we calculate the discount that is available for the user &lt;em&gt;(for example the user has a premium account or have a corporative discount so prices are lower)&lt;/em&gt;. The calculations are the business logic so they live inside a service method &lt;code&gt;calculateFinalPrice(order, discounts)&lt;/code&gt;. After we are done with the logic, we could use &lt;code&gt;UserOrderRepository&lt;/code&gt; with a method &lt;code&gt;createOrder(order)&lt;/code&gt; which contains all fields like orderId, userId, creation date etc. Inside this method, we simply write our "INSERT" statement.&lt;/p&gt;

&lt;p&gt;So we have a controller that passes the data into a service that process it and then the data is saved using the repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario B: Confirm order, choose to ship and pay for the order
&lt;/h3&gt;

&lt;p&gt;As you already see, here we have several things to work with. We have an order that should be confirmed, shipping options to be configured and money-related operations to be done.&lt;br&gt;
So in practice, we get the request in our controller and pass it to the &lt;code&gt;UserOrderService&lt;/code&gt; which handle logic that checks if the order can be confirmed with those parameters. After that, we're triggering services that have logic to work with external &lt;code&gt;ShippingService&lt;/code&gt; and &lt;code&gt;PaymentService&lt;/code&gt;. Those may contain some additional logic or utility methods that belong to them so we will need to implement some additional features for it. Finally, those services might trigger our repositories because we need to save that we need to pass the order to a shipping company and we know that the order is paid already.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario C: User creates a comment below the bought product
&lt;/h3&gt;

&lt;p&gt;The user got the order and want to give feedback &lt;em&gt;(or post the comment on the product page)&lt;/em&gt;. In this scenario, there is not much logic to work with the data &lt;em&gt;(if comment moderation is manual. If it's done by AI it could have some logic in &lt;code&gt;CommentService&lt;/code&gt; in method &lt;code&gt;checkComment(comment)&lt;/code&gt;)&lt;/em&gt;. If we have no logic there, we can simply pass the comment into &lt;code&gt;CommentRepository&lt;/code&gt; which has a method called &lt;code&gt;addComment(user, comment)&lt;/code&gt; and that's it. If no service is required you can simply trigger repository functionality from the controller.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Layered architecture is pretty simple and doesn't require developers to have big experience as well as it doesn't force developers to write too much boilerplate or deal with complicated abstractions and structures.&lt;br&gt;
If you need to design MVP or if your project is not that big (yet) consider using layered architecture as a base architecture.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>architecture</category>
    </item>
    <item>
      <title>REST API Design</title>
      <dc:creator>Blind Kai</dc:creator>
      <pubDate>Sun, 16 Jan 2022 18:41:12 +0000</pubDate>
      <link>https://dev.to/blindkai/rest-api-design-27j9</link>
      <guid>https://dev.to/blindkai/rest-api-design-27j9</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;This article is written primarily for backend developers that are looking for some practical examples of "how-to" design their REST APIs so they would be strain forward for other developers as well as for API consumers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The anatomy of the end-point path
&lt;/h2&gt;

&lt;h3&gt;
  
  
  HTTP method
&lt;/h3&gt;

&lt;p&gt;Every endpoint belongs to the HTTP method. Those methods give developers and users a basic understanding of "what action" is performed on resources on that path. It's required to use the proper HTTP method for each endpoint. The details about each of the listed below methods can be found in &lt;a href="https://datatracker.ietf.org/doc/html/rfc2616#section-9"&gt;RFC2616&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET&lt;/code&gt; should be used if the endpoint returns information about the given resource &lt;em&gt;("list items", "get the item with ID=5", "get all subitems of the item with ID=5" and so on)&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST&lt;/code&gt; should be used if the endpoint creates a resource during request or should somehow change the state of the resources &lt;em&gt;("create new item", "perform authentication")&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PUT&lt;/code&gt; is used when there is a need to completely replace a resource with an updated version. It's mostly used for update operations &lt;em&gt;("update item")&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PATCH&lt;/code&gt; is similar to &lt;code&gt;PUT&lt;/code&gt; but mostly is usable when you want to indicate, that the resource can be partly updated &lt;em&gt;("change user status to active", "grant user a permission/access")&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE&lt;/code&gt; as the name says, it indicates that the endpoint performs deletion of resource &lt;em&gt;("delete item", "delete all items")&lt;/em&gt;;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other HTTPS methods are less common to use and you probably will know if you need to use them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Endpoint path
&lt;/h3&gt;

&lt;p&gt;As we already know, the HTTP method is a verb, so to describe the endpoint path we need to use nouns (in other words "domain names").&lt;/p&gt;

&lt;p&gt;For example to create a user we write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /users          // GOOD
POST /create-user    // BAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've already specified &lt;code&gt;POST&lt;/code&gt; as a method so we know, "it's going to create a user".&lt;/p&gt;

&lt;p&gt;Another example to update user status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PATCH /users/status     // GOOD
PATCH /users/set-status // BAD do not use verbs in paths
PUT   /users/status     // BAD use proper HTTP method
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of the time you will face CRUD routes with some additional end-points to work with sub-entities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET    /users             // Get list of users
GET    /users/${userID}   // Get single user details
POST   /users             // Create a new user
PUT    /users/${userID}   // Update user
DELETE /users/${userID}   // Delete user

PATCH  /users/access      // Partly update user

GET    /users/${userID}/photos            // Get sub-entity
POST   /users/${userID}/photos            // Create sub-entity
DELETE /users/${userID}/photos/${photoID} // Delete sub-entity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Query parameters
&lt;/h3&gt;

&lt;p&gt;Often you need to specify additional parameters for pagination or some kind of filtering that is provided by your server.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pagination
&lt;/h4&gt;

&lt;p&gt;If you're not using pagination on end-points that return lists of items, you probably should, because the growth of the database request would last a long time and suddenly block your server or database from running. The user also won't be happy to wait 15 seconds for items he doesn't want to see in numbers.&lt;/p&gt;

&lt;p&gt;Example of query string with pagination:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /users?page=1&amp;amp;pageSize=25    // "Classic" pagination
GET /users?fromId=1232142        // Cursor pagination
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Filtering
&lt;/h4&gt;

&lt;p&gt;In case you need to specify some additional search parameters or return only specific entity fields you will also add them into query string and parse on the server-side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /users?search=John      // Search for user with name John
GET /users?status=active,banned&amp;amp;age=18-21,22-27,40-49 // Return only active or banned users within the specified age groups. If you want to specify few filters you separate them by ","
GET /users?online=2021-12-01,2022-01-01 // Fetch users that were online in range of dates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Sorting
&lt;/h4&gt;

&lt;p&gt;Users usually want to see "recent" items or updates, but sometimes they want to apply other sorting options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /users?sort=last_online         // Sort by last online ASC
GET /users?sort=last_online,status  // Sort by 2 fields
GET /users?sort=name&amp;amp;desc=true      // Sort by name in descending order
GET /users?sort=+name,-status       // Multisort with specifying "+"/"-" as ASC/DESC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Response HTTP status codes
&lt;/h3&gt;

&lt;p&gt;Depending on the result of the request the server should return a proper status code to indicate if the request was successfully finished or there were errors and it can't be finished.&lt;/p&gt;

&lt;p&gt;It's also a good practice to use the defined set of codes for all end-points and provide additional messages within a response or in the documentation.&lt;/p&gt;

&lt;p&gt;Those status codes are described at &lt;a href="https://datatracker.ietf.org/doc/html/rfc2616#section-10"&gt;RFC 2616&lt;/a&gt;, &lt;a href="https://datatracker.ietf.org/doc/html/rfc4918#section-11"&gt;RFC 4918&lt;/a&gt;, &lt;a href="https://datatracker.ietf.org/doc/html/rfc6585"&gt;RFC 6585&lt;/a&gt; and others.&lt;/p&gt;

&lt;p&gt;Most of the time, you would be using those status codes:&lt;/p&gt;

&lt;h4&gt;
  
  
  2xx
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;200 OK&lt;/code&gt; - Simply means that the request was successfully performed and resource is available in response.&lt;br&gt;
&lt;code&gt;201 Created&lt;/code&gt; - Mostly used in &lt;code&gt;POST&lt;/code&gt; requests as an indication that resource was successfully created and stored in the server.&lt;br&gt;
&lt;code&gt;204 No Content&lt;/code&gt; - Mostly used in &lt;code&gt;DELETE&lt;/code&gt; requests to indicate that resource doesn't exist anymore.&lt;/p&gt;

&lt;h4&gt;
  
  
  4xx:
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;400 Bad Request&lt;/code&gt; - the request doesn't satisfy validation rules and the server denies processing it. Addition details about errors can be specified in the response body.&lt;br&gt;
&lt;code&gt;401 Unautorized&lt;/code&gt; - user is not authorized to use this end-point. Most of the time this is a status code to use if the user session is timed out or access token/session token was not provided in the Authorization header or within a cookie.&lt;br&gt;
&lt;code&gt;403 Forbidden&lt;/code&gt; - if it's a response to a sing-in end-point request it simply means that "there is no user with such username &amp;amp; password combination" or that user has no right to perform the request.&lt;br&gt;
&lt;code&gt;404 Not Found&lt;/code&gt; - the resource doesn't exist or there is no end-point on this address. The additional message about the error should be provided in the response body.&lt;br&gt;
&lt;code&gt;409 Conflict&lt;/code&gt; - mostly used when performing the request is impossible due to a constraint on the server (for example user with the specified nickname already exists) or if the given entity was already modified before the user sent a request.&lt;br&gt;
&lt;code&gt;422 Unprocessable Entity&lt;/code&gt; - means that the request schema is correct and it passes validation rules, but the server can't process the request or work with that query.&lt;br&gt;
&lt;code&gt;429 Too Many Requests&lt;/code&gt; - simply means that the user sent too many requests to the server (for example if the user tries to log in too many times in 1 minute).&lt;/p&gt;

&lt;h4&gt;
  
  
  5xx
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;500 Internal Server Error&lt;/code&gt; - your server should have a handler for unexpected errors and send a response to the user if there is something wrong before shutting the server down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;It's important to use things as they were designed to be used and to provide an interface that would be intuitive and easy to work with.&lt;br&gt;
Also, don't forget to document your APIs using popular instruments like Swagger. It's helpful when you want to provide some explanations over "what does this status code mean" or "how to use filters in this end-point".&lt;br&gt;
You will get some experience only by doing things. With all the basic rules you should be fine until you will come to some specific cases.&lt;/p&gt;

</description>
      <category>rest</category>
    </item>
    <item>
      <title>Using v-model with objects in Vue3</title>
      <dc:creator>Blind Kai</dc:creator>
      <pubDate>Tue, 30 Nov 2021 20:42:24 +0000</pubDate>
      <link>https://dev.to/blindkai/objects-and-v-model-in-vue3-1l9h</link>
      <guid>https://dev.to/blindkai/objects-and-v-model-in-vue3-1l9h</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;When I was using Vue2 along with &lt;a href="https://github.com/vuejs/vue-class-component"&gt;&lt;code&gt;vue-class-component&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://github.com/kaorun343/vue-property-decorator"&gt;&lt;code&gt;vue-property-decorator&lt;/code&gt;&lt;/a&gt; it was easy to synchronize &lt;code&gt;v-models&lt;/code&gt; between components simply using &lt;a href="https://github.com/kaorun343/vue-property-decorator#-modelsyncpropname-string-event-string-options-propoptions--constructor--constructor---decorator"&gt;&lt;code&gt;@ModelSync()&lt;/code&gt;&lt;/a&gt;. When Vue 3 came out with its &lt;a href="https://v3.vuejs.org/guide/composition-api-introduction.html"&gt;Composition API&lt;/a&gt; another way was needed to achieve the same result as if Class Component was used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;If you're already familiar with the capabilities of &lt;a href="https://v3.vuejs.org/api/composition-api.html#composition-api"&gt;Composition API&lt;/a&gt;, then simply use &lt;a href="https://v3.vuejs.org/api/computed-watch-api.html#computed"&gt;&lt;code&gt;computed&lt;/code&gt;&lt;/a&gt; within &lt;a href="https://v3.vuejs.org/guide/composition-api-introduction.html#setup-component-option"&gt;&lt;code&gt;setup&lt;/code&gt;&lt;/a&gt; to update the &lt;a href="https://v3.vuejs.org/guide/component-custom-events.html#v-model-arguments"&gt;&lt;code&gt;modelValue&lt;/code&gt;&lt;/a&gt; whenever it changes.&lt;/p&gt;

&lt;p&gt;1) In child component define a model property with the default value&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;import { defineComponent } from 'vue';

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FancyComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;           &lt;span class="c1"&gt;// Declare the property&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({}),&lt;/span&gt;  &lt;span class="c1"&gt;// Do not forget about default value&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) In &lt;code&gt;setup()&lt;/code&gt; define a computed property and expose it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"theModel.foo"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;&amp;lt;!-- Usage of model --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FancyComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;emits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;update:modelValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// The component emits an event&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({}),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;emit&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  &lt;span class="c1"&gt;// Use computed to wrap the object&lt;/span&gt;
      &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;update:modelValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;theModel&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) In parent component use &lt;code&gt;v-model&lt;/code&gt; directive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;FancyComponent&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"someObject"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  TypeScript
&lt;/h2&gt;

&lt;p&gt;In the case of using TypeScript, there is one minor addition to the code above. &lt;a href="https://v3.vuejs.org/guide/typescript-support.html#annotating-props"&gt;&lt;code&gt;PropType&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/a&gt; is used it order to annotate the model type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PropType&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;OurModelType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;FancyComponent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;emits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;update:modelValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;PropType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;OurModelType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Type Annotation&lt;/span&gt;
      &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({}),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;emit&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;modelValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;update:modelValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;theModel&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it's all you need to know to pass reactive objects into your custom components as &lt;code&gt;v-model&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>vue</category>
    </item>
    <item>
      <title>Managing API layers in Vue.js with TypeScript</title>
      <dc:creator>Blind Kai</dc:creator>
      <pubDate>Sat, 17 Jul 2021 09:32:42 +0000</pubDate>
      <link>https://dev.to/blindkai/managing-api-layers-in-vue-js-with-typescript-hno</link>
      <guid>https://dev.to/blindkai/managing-api-layers-in-vue-js-with-typescript-hno</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;Almost every Single-Page Application at some point needs to get some data from the backend. Sometimes there are several sources of data like REST APIs, Web Sockets etc. It's important to manage the API layer in the right way to make it simple and easy to use in any place of your application no matter if it's store, component or another type of source file.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;If you already have some experience in development and want to check the solution here is the &lt;code&gt;FancyUserCard&lt;/code&gt; example. If some things would be hard to understand feel free to check the detailed step-by-step path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bad
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84q8ge695h60osoc9w6l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84q8ge695h60osoc9w6l.png" alt="An example of API calls in component"&gt;&lt;/a&gt;Performing API calls in the component is bad because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You make your components large and filled with logic that has nothing to do with the component itself which violates SRP;&lt;/li&gt;
&lt;li&gt;Same API methods could be used in different components which causes code duplication and violates DRY;&lt;/li&gt;
&lt;li&gt;You are importing dependencies globally and it violates the DI principle;&lt;/li&gt;
&lt;li&gt;Whenever API changes, you need to manually change every method that is needed to be modified.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Good
&lt;/h3&gt;

&lt;p&gt;To make things work better we need to slightly change our code and move all the API calls into a separate place.&lt;/p&gt;

&lt;h4&gt;
  
  
  users.api.ts
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0dc8x9ah1oa1dfe7u86v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0dc8x9ah1oa1dfe7u86v.png" alt="Users API layer file"&gt;&lt;/a&gt;In this case we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have one single &lt;code&gt;AxiosInstance&lt;/code&gt; that is configured to work with &lt;code&gt;/users&lt;/code&gt; API branch and our code becomes modular;&lt;/li&gt;
&lt;li&gt;Have all methods located in one place so it's easier to make changes and to reuse them in different components without duplicating code;&lt;/li&gt;
&lt;li&gt;Handle the successful request as well as request failure and make us able to work with both error and data object depending on request status;&lt;/li&gt;
&lt;li&gt;Provide a standardized response return type for each method so we can work with them in one way. &lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  FancyUserCard.vue
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvybn8lpk1ex9inb4shig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvybn8lpk1ex9inb4shig.png" alt="FancyUserCard component that imports API methods"&gt;&lt;/a&gt;And in our component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We are not dealing with the HTTP layer at all so our component is only responsible for rendering data that comes from the API layer;&lt;/li&gt;
&lt;li&gt;Methods return both errors and data so we can notify your user if something went wrong or simply use data that was returned by a method.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Advanced
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzplkc8f0ytelaujbhk35.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzplkc8f0ytelaujbhk35.png" alt="API methods encapsulated within a class"&gt;&lt;/a&gt;Some final changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The API call method was moved to reduce code duplication and all the methods are called using this private method.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Some other ideas
&lt;/h3&gt;

&lt;p&gt;The approach shown above is enough to handle standard API layer workflow. If you want to make it even more flexible you could think about implementing some ideas below:&lt;/p&gt;

&lt;h4&gt;
  
  
  Creating abstraction over HTTP layer&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy8w0vcscagfe88o1unsn.png" alt="Creating abstraction over HTTP layer"&gt;About the idea:
&lt;/h4&gt;

&lt;p&gt;In the example, you can see that now we have an interface for our &lt;code&gt;HttpClient&lt;/code&gt; so we could have as many implementations as we need. It works if we have different HTTP clients like &lt;code&gt;axios&lt;/code&gt;, &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;ky&lt;/code&gt; and if we will need to migrate from one to another we would simply need to rewrite our &lt;code&gt;HttpClient&lt;/code&gt; implementation in one place and it will be applied automatically in any place where we use our service;&lt;/p&gt;

&lt;h4&gt;
  
  
  Create a factory&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqa5gascfzfa22s8afqm.png" alt="Create a factory"&gt;About the idea:
&lt;/h4&gt;

&lt;p&gt;If you have few different data sources you could use some sort of factory to create the instance with needed implementation without an explicit class declaration. In this case, you just need to provide a contract interface and then implement each API method as you want.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the problem
&lt;/h2&gt;

&lt;p&gt;As you already know, dealing with API calls in your components is harmful because whenever the changes come you have plenty of work to do to maintain your code in the working state. Also, it can be pretty challenging to test components and API because they are directly and deeply coupled. We want to avoid those things while writing code so let's get through the example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;This is the code for the initial example of an API call. For simplicity let's omit other code and keep attention only on the method itself.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;axios&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.fancy-host.com/v1/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can already see, we're accessing the component &lt;code&gt;data()&lt;/code&gt; directly and use global &lt;code&gt;axios&lt;/code&gt; which forces us to type more code for setting the request configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  TODO list
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Migrate the code to a separate method;&lt;/li&gt;
&lt;li&gt;Move from &lt;code&gt;then&lt;/code&gt; syntax to &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Setup &lt;code&gt;axios&lt;/code&gt; instance;&lt;/li&gt;
&lt;li&gt;Manage methods return type;&lt;/li&gt;
&lt;li&gt;Incapsulate the method in &lt;code&gt;Class&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Refactoring
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Migrate the code to a separate method
&lt;/h3&gt;

&lt;p&gt;To start with, lest move our code to the separate file and simply export a function that accepts &lt;code&gt;userId&lt;/code&gt; as input parameter and return &lt;code&gt;user&lt;/code&gt; object if the call was successful:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;axios&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.fancy-host.com/v1/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Already an improvement! Now we can import this function whenever we need to get &lt;code&gt;User&lt;/code&gt;. We just need to specify the &lt;code&gt;userId&lt;/code&gt; and we're ready to go.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Move from &lt;code&gt;then&lt;/code&gt; syntax to &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In real world there are often situations when you need to make sequential calls. For example, when you fetch &lt;code&gt;user&lt;/code&gt; you probably want to get information about posts or comments related to user, right? Sometimes you want to perform requests in parallel and it can be really tricky if we're talking about &lt;code&gt;.then&lt;/code&gt; implementation. So why won't we make it better?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.fancy-host.com/v1/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see, now we are providing additional typings and using &lt;code&gt;await&lt;/code&gt; to stop our code from running until the API call finishes. &lt;strong&gt;remember that you're able to use &lt;code&gt;await&lt;/code&gt; only inside the &lt;code&gt;async&lt;/code&gt; function&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Setup &lt;code&gt;axios&lt;/code&gt; instance;
&lt;/h3&gt;

&lt;p&gt;Okay, so now the longest line is the one with the end-point URL. Your server host is probably not going to change often and it's better to keep your API branch set up in one place so let's get into:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axiosInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.fancy-host.com/v1/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axiosInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Much better. Now if your &lt;code&gt;/users&lt;/code&gt; API branch will change, you could simply rewrite it in the instance configuration and it will be applied to every call made using this &lt;code&gt;AxiosInstance&lt;/code&gt;. Also, now you could use something called &lt;a href="https://github.com/axios/axios#interceptors" rel="noopener noreferrer"&gt;Interceptors&lt;/a&gt; which allows you to make some additional changes to requests/responses or perform logic when a request is made or response is back. Check out the link to get more details!&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Manage methods return type
&lt;/h3&gt;

&lt;p&gt;What if I will say to you that your user doesn't understand if (and why) something went wrong .. until! Until you provide some information about "what went wrong". UX is really important to keep your user happy and make the workflow better at all. So how are we going to do that? Simply by returning both &lt;code&gt;data&lt;/code&gt; and &lt;code&gt;error&lt;/code&gt; from our API call. You could also return as many things as you need (if you need them, right?):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;APIResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;APIResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axiosInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And how it will look when we use it, for example in our &lt;code&gt;created()&lt;/code&gt; callback:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;notifyUserAboutError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So in this case, if any error happens, you would be able to react to this and perform some actions like pushing an error notification, or submit a bug report or any other logic you put in your &lt;code&gt;notifyUserAboutError&lt;/code&gt; method. Elsewise, if everything went okay, you could simply put the user object into your &lt;code&gt;Vue&lt;/code&gt; component and render fresh information.&lt;/p&gt;

&lt;p&gt;Also, if you need to return additional information (for example status code to indicate if it is &lt;code&gt;400 Bad Request&lt;/code&gt; or &lt;code&gt;401 Unautorized&lt;/code&gt; in case of failed request or if you want to get some response headers if everything was okay), you could add an object in your method return:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;code&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;APIResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;?]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;?];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;APIResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axiosInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&gt;}];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And usage:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selectedUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;notifyUserAboutError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;goToAuth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;notifyBadRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customHeader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;customHeader&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As you can see, your requests become more and more powerful but at the same time, you can make your components free from that logic and work only with those details you need.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Incapsulate the method in &lt;code&gt;Class&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;And now there is time for the final touch. Our code is already doing a great job but we can make it even better. For example, there are cases when we want to test how our components interact with other layers. At the same time, we don't want to perform real requests and it's enough to ensure that we make them correctly at all. To achieve this result we want to be able to mock our HTTP client. To make it possible, we want to "inject" a mocked instance into our module and it's hard to imagine a better way to do that than with &lt;code&gt;Class&lt;/code&gt; and its &lt;code&gt;constructor&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AxiosInstance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;APIResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And the usage:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axiosInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.fancy-host.com/v1/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;axiosInstance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this case, you don't expose your &lt;code&gt;AxiosInstance&lt;/code&gt; and provide access only thru your service public API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Hope that this article was useful for you. Do not hesitate to leave a comment if you have some other ideas or if there are any questions about the content of this post. I will update this post with detailed information about the problem, the solutions and the refactoring process soon.&lt;br&gt;
Cheers!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>vue</category>
    </item>
  </channel>
</rss>
