微信小程序 request接口的封装介绍

1. 前言

目前,微信小程序已经成为了移动端开发中极受欢迎的平台之一,其实现的数据请求功能是小程序开发中十分重要的一个环节。相信大家都了解,小程序中进行网络请求,需要使用到 wx.request() 方法。

然而在实际开发中,wx.request() 方法有一个很大的缺陷,就是它不支持Promise。 这就需要开发者自己封装一套请求接口,以便于更加方便的进行接口的调用和数据的处理。

接下来将介绍我们是如何基于Promise 封装一个网络请求的功能。

2. 封装Promise

2.1 Promise 特点

Promise是ES6提供的一种全新的异步编程解决方案,具有以下特点:

Promise的状态不受外界影响,只有异步操作完成,才会改变状态。

Promise一旦状态改变,就不会再变,任何时候都可以得到这个结果。

Promise对象的错误会被吞掉。所以在Promise封装中要特别处理错误。

2.2 Promise封装请求

我们这里封装了一个requestPromise方法来处理小程序中的请求操作。

const API_PREFIX = 'https://www.example.com/'

const requestPromise = options => {

return new Promise((resolve, reject) => {

wx.request({

url: API_PREFIX + options.url,

method: options.method || 'GET',

data: options.data || {},

header: options.header || {

'Content-Type': 'application/json'

},

success: res => {

if (res.statusCode === 200) {

resolve(res)

} else {

reject(res)

}

},

fail: error => {

reject(error)

}

})

})

}

// example

requestPromise({

url: 'user/userinfo',

method: 'POST',

data: {

username: 'xiaoming',

age: 20

},

header: {

'authorization': 'Bearer token'

},

}).then(res => {

console.log(res.data)

}).catch(error => {

console.log(error)

})

上述代码将wx.request作为一个封装后的方法返回了,将其返回值改为了Promise,这样使用时就可以使用then和catch方法处理成功或者失败的回调。

3. 拦截器

3.1 概述

拦截器可以对请求进行统一处理,包括请求之前的统一处理和响应之后的统一处理。在需要对所有请求都进行特定的预处理时,拦截器非常有用。比如可以添加 authorization 等参数,或者在请求前加入全局loading等。

3.2 实现

我们可以自定义一个中间件,来达到拓展的目的,中间件主要分为两种:请求拦截和响应拦截。下面分别介绍一下相应的内容。

3.2.1 请求拦截器

在请求前拦截请求,并加入请求数据或者header头信息。下面是一个完整的请求拦截器实现过程

首先定义一个RequestMiddware的中间件类,用来存放拦截器相关的信息:

class RequestMiddware {

constructor() {

this._middlewares = []

}

}

然后在RequestMiddware原型链上定义一个 use() 方法,用于注册请求拦截器,该方法接收一个函数作为参数:

RequestMiddware.prototype.use = function (fn) {

if (typeof fn !== 'function') {

throw new TypeError('middleware must be a function')

}

this._middlewares.push(fn)

}

在请求前遍历所有的中间件进行处理,最终返回修改后的options,在requestPromise中处理这些中间件:

requestPromise.middlewares = new RequestMiddware()

const requestPromise = options => {

return new Promise((resolve, reject) => {

const chain = []

// 请求前拦截

requestPromise.middlewares._middlewares.forEach(fn => {

chain.push(fn)

})

chain.push(request(options))

// 请求后拦截

const next = response => {

return response

}

let index = 0

const execute = data => {

const currentMiddleware = chain[index]

index++

if (currentMiddleware) {

return currentMiddleware(data, execute)

} else {

return data

}

}

execute(options)

})

}

这样,在requestPromise方法内部,就会自动对中间件进行遍历和执行了,遇到错误或者请求/响应时加入需要做的拦截操作。

3.2.2 响应拦截器

接下来介绍一个类似于请求拦截器的响应拦截器。responseMiddleware的核心点在于,使用调用栈来进行中间件的遍历,同时还需要对错误进行包装。

定义一个ResponseMiddware的中间件类,用来存放拦截器相关的信息:

class ResponseMiddware {

constructor() {

this._middlewares = []

}

}

然后在ResponseMiddware原型链上定义一个 use() 方法,用于注册请求拦截器,该方法接收一个函数作为参数:

ResponseMiddware.prototype.use = function (fn) {

if (typeof fn !== 'function') {

throw new TypeError('middleware must be a function')

}

this._middlewares.push(fn)

}

在响应后遍历所有的中间件进行处理,最终返回修改后的options,在调用resolve方法。

requestPromise.middlewares = new RequestMiddware()

requestPromise.middlewares = new ResponseMiddware()

const requestPromise = options => {

return new Promise((resolve, reject) => {

const chain = []

// 请求前拦截

requestPromise.middlewares._middlewares.forEach(fn => {

chain.push(fn)

})

chain.push(request(options))

// 响应拦截

responseHandler = data => {

const {statusCode} = data || {};

if (statusCode !== 200) {

console.log('responseError')

requestPromise.middlewares._middlewares.forEach(fn => {

const error = new Error(`Request faild with status code ${statusCode}`)

error.statusCode = statusCode

fn(error)

})

return Promise.reject({

statusCode: statusCode,

error: data.errMsg

})

}

return data

}

chain.push(responseHandler)

// 响应后拦截

const next = response => {

return response

}

let index = 0

const execute = data => {

const currentMiddleware = chain[index]

index++

if (currentMiddleware) {

return currentMiddleware(data, execute)

} else {

return data

}

}

execute(options).then(res => {

resolve(res)

}).catch(err => {

reject(err)

})

})

}

总结

整个封装的流程大致如下:

首先定义一个Promise,其将wx.request封装起来,并且返回数据。

定义一个RequestMiddware类和一个ResponseMiddware类,用于存放请求拦截器和响应拦截器的相关信息。

在requestPromise和requestPromise.middlewares中分别实例化这两个中间件类。

在requestPromise函数中,对请求的参数和header等信息进行处理。

在requestPromise函数中,使用requestPromise.middlewares._middlewares和execute方法分别遍历请求拦截器和响应拦截器进行处理,之后将处理后的结果返回。

最后,在执行所有操作之前,需要使用request来处理请求数据。

该方法的好处是封装了数据请求方法,使代码更加简洁和可维护,易于使用和处理错误。同时也方便开发者添加拦截器进行个性化定制,提高了代码的可扩展性和可重用性。希望对大家在开发小程序时具有一定的帮助。