小程序模板網(wǎng)

人人都該具備封裝思維:Taro+Es6+Promise+Ts簡(jiǎn)易構(gòu)建微信小程序的全局請(qǐng)求方法

發(fā)布時(shí)間:2020-05-15 10:22 所屬欄目:小程序開(kāi)發(fā)教程

無(wú)論是app還是小程序或者其他端,交互中請(qǐng)求無(wú)處不在。

一個(gè)優(yōu)秀的封裝類(lèi),能讓你的開(kāi)發(fā)效率事半功倍,所以封裝邏輯至關(guān)重要,當(dāng)然我也是個(gè)小菜鳥(niǎo),跟著自己的思路寫(xiě)過(guò)一些封裝方法,一方面是想不足之處還望路過(guò)的大神給予指正,二者是為新手打開(kāi)一個(gè)善于封裝思維的大門(mén),下面進(jìn)入到前置知識(shí)。

Api: cnodejs.org/api/v1

Ts: 簡(jiǎn)易的類(lèi)型聲明、接口等

Es6:結(jié)構(gòu)賦值、擴(kuò)展運(yùn)算、promise、export等

Taro:類(lèi)react,以及小程序基礎(chǔ)知識(shí)等

1.梳理Taro的請(qǐng)求 Taro.request,實(shí)現(xiàn)最簡(jiǎn)易的請(qǐng)求方法

import Taro from '@tarojs/taro'
//回調(diào)調(diào)用
function doRequestAction(){
  Taro.request({
    url: '',
    data: {},
    header: {},
    success: res => {},
    fail: err => {},
    complete: info => {}
  })
}
// promise調(diào)用
function doRequestAction(){
  Taro.request({
    url: '',
    data: {},
    header: {}
  })
  .then(res=>{})
  .catch(err=>{})
  .finally(()=>{})
}
復(fù)制代碼

其中利弊不多做介紹,我們將會(huì)用到promise的請(qǐng)求方式。

2.梳理會(huì)用到的請(qǐng)求結(jié)構(gòu),以及定義的文件分類(lèi):

  • 接口地址,也就是我們常說(shuō)的url,存放于api.ts文件中
  • 請(qǐng)求方法,也就是我們封裝的方法,我們存放于request.ts文件中
  • 接口類(lèi)型,也就是我們聲明數(shù)據(jù)類(lèi)型的文件,我們存放于inter.d.ts文件中
  • 配置文件,常用的全局請(qǐng)求域名,其他不動(dòng)參數(shù)等,我們這里只是簡(jiǎn)單的示例因此不需要,如果有需要請(qǐng)大家自行配置
文件名 作用
api.ts 存放接口地址、以及統(tǒng)一請(qǐng)求域名前綴
request.ts 封裝公共請(qǐng)求方法、以及調(diào)用方法集合
inter.d.ts ts的聲明文件,主要存放返回值類(lèi)型,請(qǐng)求參數(shù)類(lèi)型等

3.接入promise聲明自己的方法并返回自己的promise請(qǐng)求對(duì)象

我這里盡量寫(xiě)es6寫(xiě)法讓大家在今后的項(xiàng)目開(kāi)發(fā)中更加順暢的使用,當(dāng)然在自己的項(xiàng)目中請(qǐng)結(jié)合實(shí)際情況使用,不要盲目的接入一些新的寫(xiě)法。下面進(jìn)入知識(shí)點(diǎn)梳理:

  • 請(qǐng)求是否loading,真 ? 結(jié)束隱藏loading : ' '
  • loading層是否開(kāi)啟mask
  • loading文字參數(shù)可自定義
  • 請(qǐng)求失敗是否彈出我們的報(bào)錯(cuò)信息
  • url在不以http/https的情況下使用自定義接口
import Taro from '@tarojs/taro'
// 暫時(shí)考慮 req的屬性都會(huì)傳入
const doRequestAction = (req) => {
  return new Promise((resolve, reject) => {
    if (req.loading) Taro.showLoading({ title: req.title ? req.title : '數(shù)據(jù)加載中...' })
    Taro.request({
      url: /^http(s?):\/\//.test(req.url) ? req.url : '', //暫時(shí)留空
      method: 'POST',
      data: {},
      header: { 'content-type': 'application/x-www-form-urlencoded' }
    })
    .then(res => {})
    .catch(err => { 
        //報(bào)錯(cuò)提示 
    })
    .finally(() => {
      if (req.loading) Taro.hideLoading()
    })
  })
}
復(fù)制代碼

4.分離請(qǐng)求參數(shù)并使用ts聲明傳入值與類(lèi)型

1.將使用到的參數(shù)進(jìn)行分離 2.每個(gè)參數(shù)給出默認(rèn)值,如果不傳人將用默認(rèn)值代替 3.使用ts聲明參數(shù)類(lèi)型

export interface RequestBase {
  url: string, //字符串
  method: 'POST' | 'GET', //常規(guī)請(qǐng)求方式,根據(jù)項(xiàng)目要求添加
  data: any, // 每次的參數(shù)都是不固定的,因此我們暫時(shí)不聲明數(shù)據(jù)類(lèi)型
  header: RequestHeader, // 下面的requestheader類(lèi)型,
  loading: boolean, // 請(qǐng)求是否開(kāi)啟loading層
  mask: boolean, //開(kāi)啟loading層的情況下是否不能點(diǎn)擊,全屏遮罩
  title: string, //開(kāi)啟loading層的提示內(nèi)容
  failToast: boolean //如果請(qǐng)求是否,我是否直接彈出我的提示
}

export interface RequestHeader {
  'content-type': string // 表示content-type類(lèi)型必須聲明
}
復(fù)制代碼

上面的header,我重新定義了一個(gè)接口來(lái)聲明類(lèi)型,是為了更方便的去管理這個(gè)數(shù)據(jù),試想如果我們平時(shí)需要將用戶(hù)的token帶入到header里面,那么我們就會(huì)在RequestHeader中在聲明一個(gè)token字段。

所謂的接口也就相當(dāng)于我們這個(gè)數(shù)據(jù)里面有什么字段,字段是什么類(lèi)型。

所以,我們?cè)趆eader中在加入token字段,實(shí)際項(xiàng)目中,可能還會(huì)帶入加密串,時(shí)間,以及其他的輔助驗(yàn)證字段,這里只為了大家方便開(kāi)發(fā)做出示例,實(shí)際還需看項(xiàng)目聲明。

特殊提醒:ts是可以不加逗號(hào)的

export interface RequestHeader {
  'content-type': string // 表示content-type類(lèi)型必須聲明
  token: string
}
復(fù)制代碼

聲明我們的默認(rèn)參數(shù),在用戶(hù)沒(méi)有參數(shù)傳入的情況下,將會(huì)使用我們的默認(rèn)參數(shù)來(lái)輔助請(qǐng)求。

// 使用默認(rèn)參數(shù),當(dāng)數(shù)據(jù)不傳入指定字段時(shí)替代
const NormalRquestData: RequestBase = {
  url: api.DOMAIN, // 默認(rèn)請(qǐng)求地址
  method: 'GET', // 默認(rèn)get請(qǐng)求
  header : { // 默認(rèn)使用的header頭
    "content-type": 'application/x-www-form-urlencoded',
    token: ''
  },
  data: {}, // 默認(rèn)沒(méi)有參數(shù),傳入空對(duì)象
  loading: true, //默認(rèn)開(kāi)啟loading層
  mask: true, //請(qǐng)求時(shí)不需要點(diǎn)擊
  title: '數(shù)據(jù)加載中', //loading提示文字
  failToast: false // 一般我們會(huì)處理相應(yīng)業(yè)務(wù)邏輯,就不直接提示阻斷流程
}
復(fù)制代碼

思考問(wèn)題,我們?nèi)绻看蝿?dòng)態(tài) 帶上我們token? 用戶(hù)剛開(kāi)始進(jìn)入小程序,這時(shí)可能是沒(méi)有授權(quán),后面授權(quán)了我們要及時(shí)更新token來(lái)達(dá)到用戶(hù)交互目的 這時(shí)我們可以將header提出,當(dāng)然我一般會(huì)在我的狀態(tài)管理中操作,這里做個(gè)例子為大家提供思路。

  • 將token作為可選字段
  • 封裝方法每次請(qǐng)求動(dòng)態(tài)提取token
  • 方法返回類(lèi)型為我們定義的RequestHeader類(lèi)型
// inter.d.ts
export interface RequestHeader {
  'content-type': string // 表示content-type類(lèi)型必須聲明
  token?: string // token可能不存在,如果存在就是字符串類(lèi)型
}
//request.ts 獲取header頭 返回值是RequestHeader類(lèi)型
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'
  }
}
復(fù)制代碼

5.在參數(shù)某些字段不傳入的情況下,我們使用自己的參數(shù)字段進(jìn)行默認(rèn)填充

思考問(wèn)題:RequestBase參數(shù)都是必傳,但是我們的請(qǐng)求的時(shí)候參數(shù)都是可傳,如果我們將其都改為可選參數(shù),這個(gè)時(shí)候如果我們使用req.title(loading標(biāo)題)、req.url('請(qǐng)求api地址') 在ts的檢測(cè)下,這些參數(shù)都是可能不存在的,這樣我們會(huì)寫(xiě)大量判斷,那么我們的代碼就會(huì)變得相當(dāng)糟糕~!因此我們?cè)俾暶饕粋€(gè)接口用來(lái)可選參數(shù)的規(guī)范。

// 遍歷RequestBase中所有key,都改為可選參,這樣我們就只管維護(hù)RequestBase
type Request = {
  [K in keyof RequestBase]?: RequestBase[K]
}
復(fù)制代碼

改造請(qǐng)求方法,并聲明各個(gè)類(lèi)型,使ts更加規(guī)范, 將接口類(lèi)使用inter導(dǎo)入,也將之前的api改成Api統(tǒng)一首字母大寫(xiě)

import Taro from '@tarojs/taro'
import * as Api from './api'
import * as Inter from './inter.d'


// 請(qǐng)求傳入reqData參數(shù)   返回promise對(duì)象 因?yàn)槿终?qǐng)求我每次返回的類(lèi)型都是不一樣的,所以我直接any
const doRequestAction = (reqData: Inter.Request): Promise<any> => {
  // 將不存在的參數(shù)字段使用默認(rèn)值進(jìn)行替換
  let req: Inter.RequestBase = { ...NormalRquestData, ...reqData }
  return new Promise((resolve, reject) => {
    //檢測(cè)是否開(kāi)啟loading層 是否打開(kāi)msak
    if (req.loading) Taro.showLoading({ title: req.title, mask: req.mask })
    Taro.request({
      url: req.url, //引入我的接口是特殊聲明的,所以我就不檢測(cè)http/https了
      method: req.method,
      data: req.data,
      header: req.header
    })
    .then(res => {
      // 大多數(shù)請(qǐng)求中 success并不代表成功,需要我們自己檢測(cè)statusCode來(lái)確保
      if (res.statusCode === 200) {
        resolve(res.data) // 成功
      } else {
        // 如果失敗 檢測(cè)是否直接提示信息
        if(req.failToast) Taro.showToast({ title: '網(wǎng)絡(luò)不好,請(qǐng)求失??!' })
        reject(res) // 失敗
      }
    })
    .catch(err => {
      // 如果失敗 檢測(cè)是否直接提示信息
      if (req.failToast) Taro.showToast({ title: '網(wǎng)絡(luò)不好,請(qǐng)求失??!' })
      reject(err)
    })
    .finally(() => {
      // 請(qǐng)求結(jié)束 關(guān)閉loading層
      if (req.loading) Taro.hideLoading()
    })
  })
}
復(fù)制代碼

ok,請(qǐng)求方法寫(xiě)到這里我們暫時(shí)只能告一段落了

6.完善api.ts,聲明全局域名以及每個(gè)接口的定義.

//定義全局請(qǐng)求地址,因?yàn)槲覀冇玫降牡刂肥莌ttps://cnodejs.org/api/v1
export const DOMAIN: string = 'https://cnodejs.org/'
// 聲明獲取主題首頁(yè)接口地址并導(dǎo)出
export const topics: string = DOMAIN + 'api/v1/topics'
復(fù)制代碼

7.觀察api,聲明請(qǐng)求data文件,以及使用請(qǐng)求并返回promise以及返回類(lèi)型 返回類(lèi)型: cnodejs.org/api/v1/topi… 自己觀察我就不截圖了。

// 請(qǐng)求主題接口參數(shù)類(lèi)型
export interface TOPICSDATA {
  page: number,
  tab: 'ask' | 'share' | 'job' | 'good',
  limit: number,
  mdrender?: boolean
}
// 獲取主題的接口
export interface 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
}
// 作者的類(lèi)型
export interface TOPICSAUTHOR {
  loginname: string,
  avatar_url: string
}
復(fù)制代碼

8.自定義獲取方法,結(jié)合自己的請(qǐng)求方法返回新的promise對(duì)象

// 調(diào)用封裝方法 返回promise對(duì)象 得到獲取到的數(shù)據(jù)
const getTopics = (data: Inter.TOPICSDATA): Promise<Inter.TOPICS> => {
  return doRequestAction({
    url: Api.topics,
    data: data
  })
}
復(fù)制代碼

9. 頁(yè)面內(nèi)可以調(diào)用getTopics方法拿到我們的數(shù)據(jù)

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))
  },[])
復(fù)制代碼

至此,一個(gè)簡(jiǎn)易的封裝就完美的結(jié)束了,但是在實(shí)際開(kāi)發(fā)中為了自己的便利,我們會(huì)封裝很多經(jīng)常使用到的參數(shù),這里只是提供一個(gè)封裝思維,具體還需要在大家的項(xiàng)目中去思考怎么才能去優(yōu)化代碼。

10.總結(jié)

知識(shí)點(diǎn)

  • es6語(yǔ)法: ...展開(kāi)運(yùn)算, 解構(gòu)賦值, promise
  • ts:類(lèi)型聲明, 可選項(xiàng), type , any類(lèi)型 ,單個(gè)類(lèi)型定義
  • 封裝思維,文件拆分

無(wú)論是app還是小程序或者其他端,交互中請(qǐng)求無(wú)處不在。

一個(gè)優(yōu)秀的封裝類(lèi),能讓你的開(kāi)發(fā)效率事半功倍,所以封裝邏輯至關(guān)重要,當(dāng)然我也是個(gè)小菜鳥(niǎo),跟著自己的思路寫(xiě)過(guò)一些封裝方法,一方面是想不足之處還望路過(guò)的大神給予指正,二者是為新手打開(kāi)一個(gè)善于封裝思維的大門(mén),下面進(jìn)入到前置知識(shí)。

Api: cnodejs.org/api/v1

Ts: 簡(jiǎn)易的類(lèi)型聲明、接口等

Es6:結(jié)構(gòu)賦值、擴(kuò)展運(yùn)算、promise、export等

Taro:類(lèi)react,以及小程序基礎(chǔ)知識(shí)等

1.梳理Taro的請(qǐng)求 Taro.request,實(shí)現(xiàn)最簡(jiǎn)易的請(qǐng)求方法

import Taro from '@tarojs/taro'
//回調(diào)調(diào)用
function doRequestAction(){
  Taro.request({
    url: '',
    data: {},
    header: {},
    success: res => {},
    fail: err => {},
    complete: info => {}
  })
}
// promise調(diào)用
function doRequestAction(){
  Taro.request({
    url: '',
    data: {},
    header: {}
  })
  .then(res=>{})
  .catch(err=>{})
  .finally(()=>{})
}
復(fù)制代碼

其中利弊不多做介紹,我們將會(huì)用到promise的請(qǐng)求方式。

2.梳理會(huì)用到的請(qǐng)求結(jié)構(gòu),以及定義的文件分類(lèi):

  • 接口地址,也就是我們常說(shuō)的url,存放于api.ts文件中
  • 請(qǐng)求方法,也就是我們封裝的方法,我們存放于request.ts文件中
  • 接口類(lèi)型,也就是我們聲明數(shù)據(jù)類(lèi)型的文件,我們存放于inter.d.ts文件中
  • 配置文件,常用的全局請(qǐng)求域名,其他不動(dòng)參數(shù)等,我們這里只是簡(jiǎn)單的示例因此不需要,如果有需要請(qǐng)大家自行配置
文件名 作用
api.ts 存放接口地址、以及統(tǒng)一請(qǐng)求域名前綴
request.ts 封裝公共請(qǐng)求方法、以及調(diào)用方法集合
inter.d.ts ts的聲明文件,主要存放返回值類(lèi)型,請(qǐng)求參數(shù)類(lèi)型等

3.接入promise聲明自己的方法并返回自己的promise請(qǐng)求對(duì)象

我這里盡量寫(xiě)es6寫(xiě)法讓大家在今后的項(xiàng)目開(kāi)發(fā)中更加順暢的使用,當(dāng)然在自己的項(xiàng)目中請(qǐng)結(jié)合實(shí)際情況使用,不要盲目的接入一些新的寫(xiě)法。下面進(jìn)入知識(shí)點(diǎn)梳理:

  • 請(qǐng)求是否loading,真 ? 結(jié)束隱藏loading : ' '
  • loading層是否開(kāi)啟mask
  • loading文字參數(shù)可自定義
  • 請(qǐng)求失敗是否彈出我們的報(bào)錯(cuò)信息
  • url在不以http/https的情況下使用自定義接口
import Taro from '@tarojs/taro'
// 暫時(shí)考慮 req的屬性都會(huì)傳入
const doRequestAction = (req) => {
  return new Promise((resolve, reject) => {
    if (req.loading) Taro.showLoading({ title: req.title ? req.title : '數(shù)據(jù)加載中...' })
    Taro.request({
      url: /^http(s?):\/\//.test(req.url) ? req.url : '', //暫時(shí)留空
      method: 'POST',
      data: {},
      header: { 'content-type': 'application/x-www-form-urlencoded' }
    })
    .then(res => {})
    .catch(err => { 
        //報(bào)錯(cuò)提示 
    })
    .finally(() => {
      if (req.loading) Taro.hideLoading()
    })
  })
}
復(fù)制代碼

4.分離請(qǐng)求參數(shù)并使用ts聲明傳入值與類(lèi)型

1.將使用到的參數(shù)進(jìn)行分離 2.每個(gè)參數(shù)給出默認(rèn)值,如果不傳人將用默認(rèn)值代替 3.使用ts聲明參數(shù)類(lèi)型

export interface RequestBase {
  url: string, //字符串
  method: 'POST' | 'GET', //常規(guī)請(qǐng)求方式,根據(jù)項(xiàng)目要求添加
  data: any, // 每次的參數(shù)都是不固定的,因此我們暫時(shí)不聲明數(shù)據(jù)類(lèi)型
  header: RequestHeader, // 下面的requestheader類(lèi)型,
  loading: boolean, // 請(qǐng)求是否開(kāi)啟loading層
  mask: boolean, //開(kāi)啟loading層的情況下是否不能點(diǎn)擊,全屏遮罩
  title: string, //開(kāi)啟loading層的提示內(nèi)容
  failToast: boolean //如果請(qǐng)求是否,我是否直接彈出我的提示
}

export interface RequestHeader {
  'content-type': string // 表示content-type類(lèi)型必須聲明
}
復(fù)制代碼

上面的header,我重新定義了一個(gè)接口來(lái)聲明類(lèi)型,是為了更方便的去管理這個(gè)數(shù)據(jù),試想如果我們平時(shí)需要將用戶(hù)的token帶入到header里面,那么我們就會(huì)在RequestHeader中在聲明一個(gè)token字段。

所謂的接口也就相當(dāng)于我們這個(gè)數(shù)據(jù)里面有什么字段,字段是什么類(lèi)型。

所以,我們?cè)趆eader中在加入token字段,實(shí)際項(xiàng)目中,可能還會(huì)帶入加密串,時(shí)間,以及其他的輔助驗(yàn)證字段,這里只為了大家方便開(kāi)發(fā)做出示例,實(shí)際還需看項(xiàng)目聲明。

特殊提醒:ts是可以不加逗號(hào)的

export interface RequestHeader {
  'content-type': string // 表示content-type類(lèi)型必須聲明
  token: string
}
復(fù)制代碼

聲明我們的默認(rèn)參數(shù),在用戶(hù)沒(méi)有參數(shù)傳入的情況下,將會(huì)使用我們的默認(rèn)參數(shù)來(lái)輔助請(qǐng)求。

// 使用默認(rèn)參數(shù),當(dāng)數(shù)據(jù)不傳入指定字段時(shí)替代
const NormalRquestData: RequestBase = {
  url: api.DOMAIN, // 默認(rèn)請(qǐng)求地址
  method: 'GET', // 默認(rèn)get請(qǐng)求
  header : { // 默認(rèn)使用的header頭
    "content-type": 'application/x-www-form-urlencoded',
    token: ''
  },
  data: {}, // 默認(rèn)沒(méi)有參數(shù),傳入空對(duì)象
  loading: true, //默認(rèn)開(kāi)啟loading層
  mask: true, //請(qǐng)求時(shí)不需要點(diǎn)擊
  title: '數(shù)據(jù)加載中', //loading提示文字
  failToast: false // 一般我們會(huì)處理相應(yīng)業(yè)務(wù)邏輯,就不直接提示阻斷流程
}
復(fù)制代碼

思考問(wèn)題,我們?nèi)绻看蝿?dòng)態(tài) 帶上我們token? 用戶(hù)剛開(kāi)始進(jìn)入小程序,這時(shí)可能是沒(méi)有授權(quán),后面授權(quán)了我們要及時(shí)更新token來(lái)達(dá)到用戶(hù)交互目的 這時(shí)我們可以將header提出,當(dāng)然我一般會(huì)在我的狀態(tài)管理中操作,這里做個(gè)例子為大家提供思路。

  • 將token作為可選字段
  • 封裝方法每次請(qǐng)求動(dòng)態(tài)提取token
  • 方法返回類(lèi)型為我們定義的RequestHeader類(lèi)型
// inter.d.ts
export interface RequestHeader {
  'content-type': string // 表示content-type類(lèi)型必須聲明
  token?: string // token可能不存在,如果存在就是字符串類(lèi)型
}
//request.ts 獲取header頭 返回值是RequestHeader類(lèi)型
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'
  }
}
復(fù)制代碼

5.在參數(shù)某些字段不傳入的情況下,我們使用自己的參數(shù)字段進(jìn)行默認(rèn)填充

思考問(wèn)題:RequestBase參數(shù)都是必傳,但是我們的請(qǐng)求的時(shí)候參數(shù)都是可傳,如果我們將其都改為可選參數(shù),這個(gè)時(shí)候如果我們使用req.title(loading標(biāo)題)、req.url('請(qǐng)求api地址') 在ts的檢測(cè)下,這些參數(shù)都是可能不存在的,這樣我們會(huì)寫(xiě)大量判斷,那么我們的代碼就會(huì)變得相當(dāng)糟糕~!因此我們?cè)俾暶饕粋€(gè)接口用來(lái)可選參數(shù)的規(guī)范。

// 遍歷RequestBase中所有key,都改為可選參,這樣我們就只管維護(hù)RequestBase
type Request = {
  [K in keyof RequestBase]?: RequestBase[K]
}
復(fù)制代碼

改造請(qǐng)求方法,并聲明各個(gè)類(lèi)型,使ts更加規(guī)范, 將接口類(lèi)使用inter導(dǎo)入,也將之前的api改成Api統(tǒng)一首字母大寫(xiě)

import Taro from '@tarojs/taro'
import * as Api from './api'
import * as Inter from './inter.d'


// 請(qǐng)求傳入reqData參數(shù)   返回promise對(duì)象 因?yàn)槿终?qǐng)求我每次返回的類(lèi)型都是不一樣的,所以我直接any
const doRequestAction = (reqData: Inter.Request): Promise<any> => {
  // 將不存在的參數(shù)字段使用默認(rèn)值進(jìn)行替換
  let req: Inter.RequestBase = { ...NormalRquestData, ...reqData }
  return new Promise((resolve, reject) => {
    //檢測(cè)是否開(kāi)啟loading層 是否打開(kāi)msak
    if (req.loading) Taro.showLoading({ title: req.title, mask: req.mask })
    Taro.request({
      url: req.url, //引入我的接口是特殊聲明的,所以我就不檢測(cè)http/https了
      method: req.method,
      data: req.data,
      header: req.header
    })
    .then(res => {
      // 大多數(shù)請(qǐng)求中 success并不代表成功,需要我們自己檢測(cè)statusCode來(lái)確保
      if (res.statusCode === 200) {
        resolve(res.data) // 成功
      } else {
        // 如果失敗 檢測(cè)是否直接提示信息
        if(req.failToast) Taro.showToast({ title: '網(wǎng)絡(luò)不好,請(qǐng)求失??!' })
        reject(res) // 失敗
      }
    })
    .catch(err => {
      // 如果失敗 檢測(cè)是否直接提示信息
      if (req.failToast) Taro.showToast({ title: '網(wǎng)絡(luò)不好,請(qǐng)求失??!' })
      reject(err)
    })
    .finally(() => {
      // 請(qǐng)求結(jié)束 關(guān)閉loading層
      if (req.loading) Taro.hideLoading()
    })
  })
}
復(fù)制代碼

ok,請(qǐng)求方法寫(xiě)到這里我們暫時(shí)只能告一段落了

6.完善api.ts,聲明全局域名以及每個(gè)接口的定義.

//定義全局請(qǐng)求地址,因?yàn)槲覀冇玫降牡刂肥莌ttps://cnodejs.org/api/v1
export const DOMAIN: string = 'https://cnodejs.org/'
// 聲明獲取主題首頁(yè)接口地址并導(dǎo)出
export const topics: string = DOMAIN + 'api/v1/topics'
復(fù)制代碼

7.觀察api,聲明請(qǐng)求data文件,以及使用請(qǐng)求并返回promise以及返回類(lèi)型 返回類(lèi)型: cnodejs.org/api/v1/topi… 自己觀察我就不截圖了。

// 請(qǐng)求主題接口參數(shù)類(lèi)型
export interface TOPICSDATA {
  page: number,
  tab: 'ask' | 'share' | 'job' | 'good',
  limit: number,
  mdrender?: boolean
}
// 獲取主題的接口
export interface 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
}
// 作者的類(lèi)型
export interface TOPICSAUTHOR {
  loginname: string,
  avatar_url: string
}
復(fù)制代碼

8.自定義獲取方法,結(jié)合自己的請(qǐng)求方法返回新的promise對(duì)象

// 調(diào)用封裝方法 返回promise對(duì)象 得到獲取到的數(shù)據(jù)
const getTopics = (data: Inter.TOPICSDATA): Promise<Inter.TOPICS> => {
  return doRequestAction({
    url: Api.topics,
    data: data
  })
}
復(fù)制代碼

9. 頁(yè)面內(nèi)可以調(diào)用getTopics方法拿到我們的數(shù)據(jù)

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))
  },[])
復(fù)制代碼

至此,一個(gè)簡(jiǎn)易的封裝就完美的結(jié)束了,但是在實(shí)際開(kāi)發(fā)中為了自己的便利,我們會(huì)封裝很多經(jīng)常使用到的參數(shù),這里只是提供一個(gè)封裝思維,具體還需要在大家的項(xiàng)目中去思考怎么才能去優(yōu)化代碼。

10.總結(jié)

知識(shí)點(diǎn)

  • es6語(yǔ)法: ...展開(kāi)運(yùn)算, 解構(gòu)賦值, promise
  • ts:類(lèi)型聲明, 可選項(xiàng), type , any類(lèi)型 ,單個(gè)類(lèi)型定義
  • 封裝思維,文件拆分

 

 

 


易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開(kāi)源 碼云倉(cāng)庫(kù):starfork
本文地址:http://22321a.com/wxmini/doc/course/25184.html 復(fù)制鏈接 如需定制請(qǐng)聯(lián)系易優(yōu)客服咨詢(xún):800182392 點(diǎn)擊咨詢(xún)
QQ在線(xiàn)咨詢(xún)