# request 请求函数

本章节,我们主要实现request请求处理函数的功能

# 代码

我们先来看一下代码的实现,代码在wx-axios/lib/adapters/request.js

import buildFullPath from "../core/buildFullPath";
import Base64 from "../helpers/base64";
import buildURL from "../helpers/buildURL";
import { forEach } from "../utils";
import settle from "../core/settle";
import enhanceError from "../core/enhanceError";

function requestAdapter(config) {
  return new Promise((resolve, reject) => {
    let request;
    const requestHeaders = config.headers;
    // http basic 认证
    if (config.auth) {
      var username = config.auth.username || "";
      // 密码
      var password = config.auth.password
        ? decodeURI(encodeURIComponent(config.auth.password))
        : "";
      requestHeaders.Authorization =
        "Basic " + Base64.decode(username + ":" + password);
    }
    // xsrf改成从wx.getStorageSync中读取
    const xsrfValue = config.xsrfStorageName
      ? wx.getStorageSync(config.xsrfStorageName)
      : undefined;
    if (xsrfValue) {
      requestHeaders[config.xsrfHeaderName] = xsrfValue;
    }
    const fullPath = buildFullPath(config.baseURL, config.url);

    const successFn = (res) => {
      const response = {
        data: res.data,
        status: res.statusCode,
        statusText: res.errMsg,
        headers: res.header,
        config,
        request: request,
      };
      settle(resolve, reject, response);
    };

    const failFn = (error) => {
      reject(enhanceError(error, config, null, request, null));
    };

    const options = {
      url: buildURL(fullPath, config.params, config.paramsSerializer),
      header: requestHeaders,
      method: config.method.toUpperCase(),
      success: successFn,
      fail: failFn,
    };
    forEach(
      [
        "data",
        "timeout",
        "dataType",
        "responseType",
        "enableHttp2",
        "enableQuic",
        "enableCache",
        "enableHttpDNS",
        "httpDNSServiceId",
      ],
      (key) => {
        if (key in config) {
          options[key] = config[key];
        }
      }
    );
    if (config.cancelToken) {
      config.cancelToken.then((cancel) => {
        if (!request) {
          return;
        }
        request.abort();
        reject(cancel);
      });
    }

    request = wx.request(options);
  });
}

export default requestAdapter;

# 分析

我们可以看见request请求处理函数执行流程如下:

  • 根据auth配置项是否开启,添加自定义请求头Authorization

  • 根据xsrfStorageNamexsrfHeaderName配置项添加自定义请求头,实现xsrf防御

  • 根据baseURLurl配置项构建完整的请求地址

  • 构建wx.request请求参数

  • 通过循环将request请求处理函数特有的配置项和通用配置项添加进wx.request请求参数中

  • 监听外部取消请求事件

  • 使用wx.requestAPI 发送请求

相比于axios的请求处理函数,我们的这个request请求处理函数流程要简单很多,实现起来也是很简单,无需监听一大堆事件。

wx.request请求参数中,success为请求成功处理事件,fail为请求失败处理事件

success处理函数中,响应头微信小程序也已经返回来给我们,是一个 json 对象,我们也无需进行格式化。最后通过调用settle函数根据自定义请求/上传/下载校验函数来决定,请求是成功状态还是失败状态

fail处理函数中,使用enhanceError函数对error错误对象添加额外的属性,并返回该错误对象

对于取消请求,wx.request返回的对象也提供了abort方法来取消请求

# 总结

因为wx.request已经是封装好的一个请求 API,我们算是对他进行了二次封装,所以实现起来相对比较简单。

通过本章节的学习,相信大家对微信小程序是如何发送一个请求已经有了一定的了解了