当前位置: 面试刷题>> 你提到对 umi-request 请求库进行改造和封装,能否详细说明你添加的全局请求拦截和全局异常处理逻辑是如何实现的?


在软件开发中,对请求库如umi-request进行改造和封装,以实现全局请求拦截和全局异常处理,是提升应用稳定性和用户体验的重要一环。以下我将详细阐述这一过程的实现逻辑,并结合示例代码,以高级程序员的视角进行说明。

全局请求拦截

全局请求拦截主要用于在发送请求前统一处理一些公共逻辑,如添加认证信息、设置统一的请求头、记录请求日志等。在umi-request的基础上,我们可以通过中间件(Middleware)或装饰器(Decorator,如果语言支持)来实现这一功能。由于umi-request本身可能不支持装饰器,我们将采用中间件的方式。

实现步骤

  1. 定义中间件函数:中间件函数将接收请求配置作为输入,并返回一个新的请求配置(可能已修改)或直接返回响应(用于拦截请求)。

  2. 在请求发送前应用中间件:在封装后的请求函数内部,遍历所有定义好的中间件,按顺序执行它们,并将请求配置作为参数传递。

  3. 中间件中执行公共逻辑:在每个中间件中,可以添加如设置请求头、添加token等逻辑。

示例代码

// middleware/auth.js
function authMiddleware(config) {
  // 假设我们有一个函数getToken来获取认证token
  const token = getToken();
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
}

// 封装后的请求函数
function customRequest(config) {
  const middlewares = [authMiddleware]; // 中间件数组
  let currentConfig = {...config};

  // 应用中间件
  for (let middleware of middlewares) {
    currentConfig = middleware(currentConfig);
    if (currentConfig instanceof Promise) {
      // 如果中间件返回Promise,表示有异步操作,等待完成
      return currentConfig.then(newConfig => customRequest(newConfig));
    }
  }

  // 假设umiRequest是umi-request的实例
  return umiRequest(currentConfig);
}

// 使用
customRequest({
  url: '/api/data',
  method: 'get'
}).then(response => {
  console.log(response.data);
}).catch(error => {
  console.error('请求出错', error);
});

全局异常处理

全局异常处理用于捕获请求过程中发生的错误,并进行统一处理,如错误上报、用户提示等。在umi-request中,我们可以通过在请求返回的Promise链中添加.catch来实现。但为了更好的封装和复用,我们通常会创建一个全局的错误处理函数。

实现步骤

  1. 定义错误处理函数:该函数接收错误对象作为参数,执行相应的错误处理逻辑,如错误上报、用户提示等。

  2. 在请求函数中添加错误处理:在封装后的请求函数中,对umi-request的返回值使用.then(...).catch(errorHandler)结构,其中errorHandler是前面定义的错误处理函数。

示例代码

// errorHandler.js
function errorHandler(error) {
  // 错误上报逻辑(假设有一个reportError函数)
  reportError(error);

  // 用户提示逻辑
  if (process.env.NODE_ENV !== 'production') {
    console.error('请求发生错误:', error);
  }

  // 返回一个错误对象给调用者,便于链式调用或进一步处理
  return Promise.reject(error);
}

// 在封装请求函数中使用
function customRequest(config) {
  // ... 中间件处理逻辑 ...

  return umiRequest(currentConfig)
    .then(response => response)
    .catch(errorHandler);
}

// 使用方式与前面相同

总结

通过上述方式,我们成功地在umi-request的基础上实现了全局请求拦截和全局异常处理。这样的封装不仅提高了代码的重用性和可维护性,还增强了应用的健壮性和用户体验。在实际项目中,根据具体需求,还可以进一步扩展和优化这些功能,比如添加超时重试、缓存控制等。此外,提到的“码小课”网站,作为学习资源的分享平台,可以为开发者提供更多深入的技术探讨和实践案例,助力技术成长。

推荐面试题