Requests are everywhere in the interaction, whether app, applets or other ends.

A wrapper class, the development efficiency can let you get twice the result with half the effort, so it is very important to encapsulate logic, of course I am a rookie, follow wrote some of his thoughts encapsulation method, on the one hand is to deficiencies still hope passing by the great god give correct, they are for the novice, that opens the door to a good encapsulation thinking into the front knowledge below.

Api:cnodejs.org/api/v1

Ts: Simple type declarations, interfaces, etc

Es6: structure assignment, extended operation, Promise, export, etc

Taro: Classes like React and basic knowledge of small programs


Taro. Request, implement the easiest way to request them

import Taro from '@tarojs/taro'// call backfunction doRequestAction(){
  Taro.request({
    url: ' ', data: {}, the header: {}, success: res = > {}, fail: err = > {}, complete: info = > {}})} / / promise callsfunction doRequestAction(){
  Taro.request({
    url: ' ',
    data: {},
    header: {}
  })
  .then(res=>{})
  .catch(err=>{})
  .finally(()=>{})
}
Copy the code

There are few advantages and disadvantages to introduce, we will use the promise request.

2. Sort out the request structure that will be used and the file classification defined:

  • Interface addresses, also known as urls, are stored in api.ts files
  • The request methods, which we encapsulate, are stored in request.ts
  • The interface type, which is the file we declare the data type, we store in the Inter.d. ts file
  • Configuration file, common global request domain name, other fixed parameters, etc., we are just a simple example here so do not need, if necessary, please configure yourself
The file name role
api.ts Store the interface address and the unified request domain name prefix
request.ts Encapsulates a collection of common request methods, as well as calling methods
inter.d.ts Ts declaration file, mainly store return value type, request parameter type and so on

3. Add a promise to declare its own method and return its own promise request object

Here I try to write THE ES6 writing method so that you can use it more smoothly in the future project development. Of course, please use it according to the actual situation in your own project, and do not blindly add some new writing methods. Below enter knowledge point comb:

  • Is the request loading, true? End hiding loading: ‘ ‘
  • Whether mask is enabled for the loading layer
  • The loading text parameter can be customized
  • Request failed whether to pop up our error message
  • The URL uses a custom interface without HTTP/HTTPS
import Taro from '@tarojs/taro'// Consider for a moment that req attributes are passed to constdoRequestAction = (req) => {
  return new Promise((resolve, reject) => {
    if (req.loading) Taro.showLoading({ title: req.title ? req.title : 'Data loading... '}) Taro.request({ url: /^http(s?) :\/\//.test(req.url) ? req.url :' '// method:'POST',
      data: {},
      header: { 'content-type': 'application/x-www-form-urlencoded'}}). Then (res = > {}). The catch (err = > {/ / an error prompt}). The finally (() = > {if (req.loading) Taro.hideLoading()
    })
  })
}
Copy the code

4. Separate the request parameters and declare the incoming values and types using TS

1. Separate the parameters

2. The default value is given for each parameter. If no default value is sent, the default value will be used

3. Use TS to declare parameter types

exportInterface RequestBase {url: string, // string method:'POST' | 'GET'Header: RequestHeader; // RequestHeader loading: Mask: Boolean, // Whether loading layer is enabled // Whether loading layer cannot be enabled // Whether full screen mask title: string, // failToast: Boolean // If the request fails, do I just pop up my prompt}export interface RequestHeader {
  'content-type': string // content-type must be declared}Copy the code

For the header above, I redefined an interface to declare the type, in order to facilitate the management of this data. Imagine if we usually need to put the user’s token into the header, then we will declare a token field in the RequestHeader.

The so-called interface is equivalent to what fields we have in this data and what types of fields.

Therefore, we add the token field in the header. In actual projects, encryption string, time, and other auxiliary verification fields may also be introduced. Here is just for the convenience of development to make examples.

Special note: TS can be used without commas

export interface RequestHeader {
  'content-type'Content-type token must be declared: string}Copy the code

Declare our default parameters, which will be used to assist the request if no parameters are passed in by the user.

// Use default parameters instead of const NormalRquestData: RequestBase = {url: api.domain, // Default request address method:'GET'// The default get request header: {// The default header to use"content-type": 'application/x-www-form-urlencoded',
    token: ' '}, data: {}, // No arguments by default.true// Enable loading layer mask by default:true// Request without clicking title:'Data loading'//loading prompts failToast:false}}}}}}}Copy the code

Consider the question, how do we dynamically bring our token every time? At the beginning, the user may not be authorized to enter the small program. Later, we need to update the token in time to achieve the purpose of user interaction. At this time, we can raise the header.

  • Make token an optional field
  • The encapsulation method dynamically extracts tokens on each request
  • The method return type is the RequestHeader type we defined
// inter.d.ts
export interface RequestHeader {
  'content-type': string // Indicates that the content-type must declare the token? } // Request. Ts retrieves the header and returns the value of type RequestHeader const getRequestHeader = (): RequestHeader => {let token: string = Taro.getStorageSync('token')
  return token ? {
    "content-type": 'application/x-www-form-urlencoded',
    token: token
  } : {
    "content-type": 'application/x-www-form-urlencoded'}}Copy the code

5. We use our own parameter fields for default padding in cases where some parameter fields are not passed in

Question to consider: Req.title (loading title), req.url(‘ requesting API address ‘), these parameters may not exist if we use req.title(loading title), req.url(‘ requesting API address ‘). We would write a lot of judgments, and our code would be pretty bad! So let’s declare another specification of the interface for optional parameters.

// Iterate through all the keys in the RequestBase, making them optional, so we can just maintain the RequestBasetype Request = {
  [K inkeyof RequestBase]? : RequestBase[K] }Copy the code

Transform the request method, and declare each type, make TS more standard, import the interface class using Inter, also change the previous API to API uniform uppercase

import Taro from '@tarojs/taro'
import * as Api from './api'
import * as Inter from './inter.d'// The request is passed in as a reqData parameter and returns a Promise object. Since the type of the global request I return is different each time, I use any constdoRequestAction = (reqData: inter.request): Promise<any> => {// Replace nonexistent parameter fields with default valuesletreq: Inter.RequestBase = { ... NormalRquestData, ... reqData }returnNew Promise((resolve, reject) => {// Check whether loading layer is enabled and whether MSAK is enabledif(req.loading) Taro.showLoading({ title: req.title, mask: req.mask }) Taro.request({ url: Method: req.method, data: req.data, header: Req.header}).then(res => {// Success does not represent success in most requests and we need to check statusCode ourselves to make sureif(res.statuscode === 200) {resolve(res.data) // succeed}else{// Check whether a message is displayed if a failure occursif(req.failToast) Taro.showToast({ title: 'Network is bad, request failed! '}) reject(res) // fail}}). Catch (err => {// Check whether a message is displayed if a failure occursif (req.failToast) Taro.showToast({ title: 'Network is bad, request failed! '}) reject(err)}).finally(() => {// Request end to close the loading layerif (req.loading) Taro.hideLoading()
    })
  })
}
Copy the code

Ok, so I’m going to leave the request method here for now

6. Improve apI.ts, declare the global domain name and definition of each interface.

/ / define global request address, because we use the address is https://cnodejs.org/api/v1export const DOMAIN: string = 'https://cnodejs.org/'// Declare the interface address of the topic home page and export itexport const topics: string = DOMAIN + 'api/v1/topics'
Copy the code

7. Observe the API, declare the request data file, and use the request and return the promise and return type

Return type: cnodejs.org/api/v1/topi… I’m not going to take screenshots.

// Request topic interface parameter typeexport interface TOPICSDATA {
  page: number,
  tab: 'ask' | 'share' | 'job' | 'good'.limit: number, mdrender? : Boolean} // Get the interface for the topicexportinterface TOPICS { id: string, author_id: string, tab: string, content: string, title: string, last_reply_at: string, good: boolean, top: boolean, reply_count: number, visit_count: number, create_at: string, author: TOPICSAUTHOR} // The type of authorexport interface TOPICSAUTHOR {
  loginname: string,
  avatar_url: string
}
Copy the code

8. Customize the fetch method and return a new Promise object in combination with your own request method

Const getTopics = (data: Inter.TOPICSDATA): Promise<Inter.TOPICS> => {return doRequestAction({
    url: Api.topics,
    data: data
  })
}
Copy the code

9. We can call the getTopics method to get our data in the page

import { getTopics } from '.. /.. /utils/request/request'
import { TOPICSDATA } from '.. /.. /utils/request/inter'

useEffect(()=>{
    let data: TOPICSDATA= {
      page: 1,
      tab: 'ask'.limit: 10
    }
    getTopics(data).then(res=>console.log(res))
  },[])
Copy the code

At this point, a simple encapsulation on the perfect end, but in the actual development for their own convenience, we will encapsulate a lot of commonly used parameters, here is just to provide a encapsulation thinking, specific also need to think about how to optimize the code in your project.

10. Summary

knowledge

  • Es6 syntax:… Expand operations, deconstruct assignments, promise
  • Ts: Type declaration, optional, type, any type, single type definition
  • Encapsulate thinking, file split

Code connection: pan.baidu.com/s/1DZ9u7U1f… Password: t7rc

Finally, if this article is useful to you, please light up a like, thank you very much, if there are good comments or suggestions in the code, please feel free to comment.