or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

api-interceptors.mdconfig-compilation.mdevent-system.mdframework-runtime.mdindex.mdmp-runtime.mdutility-functions.mdwxs-utilities.md
tile.json

api-interceptors.mddocs/

API Interceptors

Middleware system for intercepting and modifying API calls before execution and after completion. Supports both global interceptors that apply to all API calls and method-specific interceptors for targeted API modification.

Capabilities

Adding Interceptors

Add interceptors to modify API behavior globally or for specific methods.

/**
 * Add global or method-specific interceptors for API calls
 * @param method - API method name for specific interceptor, or interceptor config for global
 * @param option - Interceptor configuration with hook functions (optional for global)
 */
function addInterceptor(method: string | InterceptorConfig, option?: InterceptorConfig): void;

Usage Examples:

import uni from "@dcloudio/uni-mp-weixin";

// Add global interceptor for all API calls
uni.addInterceptor({
  invoke(args) {
    console.log('API called with args:', args);
    // Modify request arguments globally
    return args;
  },
  success(res) {
    console.log('API succeeded:', res);
    return res;
  },
  fail(err) {
    console.error('API failed:', err);
    return err;
  },
  complete(res) {
    console.log('API completed:', res);
    return res;
  }
});

// Add interceptor for specific API method
uni.addInterceptor('request', {
  invoke(args) {
    // Add authentication headers
    args.header = args.header || {};
    args.header.Authorization = 'Bearer ' + getToken();
    
    // Add request timestamp
    args.data = args.data || {};
    args.data.timestamp = Date.now();
    
    console.log('Request intercepted:', args);
    return args;
  },
  success(res) {
    console.log('Request successful:', res);
    // Process response data
    if (res.data && res.data.code === 200) {
      res.data = res.data.result;
    }
    return res;
  },
  fail(err) {
    console.error('Request failed:', err);
    // Handle authentication errors
    if (err.statusCode === 401) {
      uni.navigateTo({ url: '/pages/login/login' });
    }
    return err;
  }
});

// Add interceptor for showToast
uni.addInterceptor('showToast', {
  invoke(args) {
    // Standardize toast duration
    args.duration = args.duration || 2000;
    // Add default icon if not specified
    if (!args.icon) {
      args.icon = 'none';
    }
    return args;
  }
});

Removing Interceptors

Remove specific interceptors or all interceptors for a method.

/**
 * Remove interceptors for API calls
 * @param method - API method name for specific removal, or interceptor config for global removal
 * @param option - Specific interceptor configuration to remove (optional)
 */
function removeInterceptor(method: string | InterceptorConfig, option?: InterceptorConfig): void;

Usage Examples:

import uni from "@dcloudio/uni-mp-weixin";

// Remove specific interceptor function
const requestInterceptor = {
  invoke(args) {
    // Add auth header
    args.header = args.header || {};
    args.header.Authorization = 'Bearer ' + token;
    return args;
  }
};

uni.addInterceptor('request', requestInterceptor);
// Later, remove the specific interceptor
uni.removeInterceptor('request', requestInterceptor);

// Remove all interceptors for a specific method
uni.removeInterceptor('request');

// Remove global interceptor
const globalInterceptor = {
  invoke(args) {
    console.log('Global invoke');
    return args;
  }
};

uni.addInterceptor(globalInterceptor);
// Remove global interceptor
uni.removeInterceptor(globalInterceptor);

Interceptor Hooks

Interceptors support multiple hook points in the API call lifecycle.

interface InterceptorConfig {
  /** Called before API execution with request arguments */
  invoke?: (args: any) => any;
  /** Called when API succeeds with success result */
  success?: (result: any) => any;
  /** Called when API fails with error information */
  fail?: (error: any) => any;
  /** Called when API completes (success or fail) with result */
  complete?: (result: any) => any;
  /** Called to modify the final return value */
  returnValue?: (value: any) => any;
}

Common Interceptor Patterns

Authentication Interceptor

Automatically add authentication tokens to API requests:

uni.addInterceptor('request', {
  invoke(args) {
    // Get token from storage
    const token = uni.getStorageSync('authToken');
    
    if (token) {
      args.header = args.header || {};
      args.header.Authorization = `Bearer ${token}`;
    }
    
    return args;
  },
  fail(error) {
    // Handle auth errors
    if (error.statusCode === 401) {
      // Token expired, redirect to login
      uni.removeStorageSync('authToken');
      uni.reLaunch({ url: '/pages/login/login' });
    }
    return error;
  }
});

Error Handling Interceptor

Global error handling and user feedback:

uni.addInterceptor({
  fail(error) {
    // Log all API errors
    console.error('API Error:', error);
    
    // Show user-friendly error messages
    const errorMessage = getErrorMessage(error);
    uni.showToast({
      title: errorMessage,
      icon: 'none',
      duration: 3000
    });
    
    return error;
  }
});

function getErrorMessage(error) {
  const errorMap = {
    400: 'Invalid request',
    401: 'Authentication required',
    403: 'Access denied',
    404: 'Resource not found',
    500: 'Server error'
  };
  
  return errorMap[error.statusCode] || 'Network error';
}

Response Transformation Interceptor

Standardize API response format:

uni.addInterceptor('request', {
  success(res) {
    // Standardize response structure
    if (res.data && typeof res.data === 'object') {
      // Extract data from wrapper
      if (res.data.code === 200 && res.data.data) {
        res.data = res.data.data;
      } else if (res.data.success && res.data.result) {
        res.data = res.data.result;
      }
    }
    
    return res;
  }
});

Loading State Interceptor

Automatically manage loading states:

let loadingCount = 0;

uni.addInterceptor('request', {
  invoke(args) {
    // Show loading if not already shown
    if (loadingCount === 0) {
      uni.showLoading({ title: 'Loading...' });
    }
    loadingCount++;
    
    return args;
  },
  complete(res) {
    // Hide loading when all requests complete
    loadingCount--;
    if (loadingCount === 0) {
      uni.hideLoading();
    }
    
    return res;
  }
});

Request Retry Interceptor

Automatically retry failed requests:

uni.addInterceptor('request', {
  fail(error) {
    // Only retry on network errors
    if (error.errno && error.errno !== 0) {
      const retryCount = error._retryCount || 0;
      const maxRetries = 3;
      
      if (retryCount < maxRetries) {
        console.log(`Retrying request (${retryCount + 1}/${maxRetries})`);
        
        // Add retry count to track attempts
        const originalArgs = error._originalArgs;
        if (originalArgs) {
          originalArgs._retryCount = retryCount + 1;
          
          // Retry after delay
          setTimeout(() => {
            uni.request(originalArgs);
          }, 1000 * (retryCount + 1));
        }
      }
    }
    
    return error;
  }
});

Data Validation Interceptor

Validate request data before sending:

uni.addInterceptor('request', {
  invoke(args) {
    // Validate required fields
    if (args.method === 'POST' && args.url.includes('/api/users')) {
      const data = args.data || {};
      const requiredFields = ['name', 'email'];
      
      for (const field of requiredFields) {
        if (!data[field]) {
          throw new Error(`Missing required field: ${field}`);
        }
      }
      
      // Validate email format
      if (data.email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)) {
        throw new Error('Invalid email format');
      }
    }
    
    return args;
  }
});

Built-in Interceptors

The package includes several built-in interceptors:

Promise Interceptor

Converts callback-style APIs to Promise-based returns:

// Built-in promise interceptor
const promiseInterceptor = {
  returnValue(res) {
    if (!isPromise(res)) {
      return res;
    }
    return res.then(res => {
      return res[1]; // Extract success result
    }).catch(res => {
      return res[0]; // Extract error result
    });
  }
};

// Access built-in interceptors
uni.interceptors.promiseInterceptor;

Types

// Main interceptor configuration interface
interface InterceptorConfig {
  /** Called before API execution with request arguments */
  invoke?: (args: any) => any;
  /** Called when API succeeds with success result */
  success?: (result: any) => any;
  /** Called when API fails with error information */
  fail?: (error: any) => any;
  /** Called when API completes (success or fail) with result */
  complete?: (result: any) => any;
  /** Called to modify the final return value */
  returnValue?: (value: any) => any;
}

// Built-in interceptors object
interface Interceptors {
  promiseInterceptor: InterceptorConfig;
}