axios為什麼可以使用物件和函式兩種方式呼叫?是如何實現的?

王铁柱6發表於2024-12-06

Axios 可以使用物件和函式兩種方式呼叫,是因為它的核心 API 設計利用了函式過載和 JavaScript 的靈活性。 本質上,Axios 暴露的頂層 axios 物件既是一個函式,又是一個擁有屬性的物件。

以下是它的實現方式:

  1. Axios 物件是一個函式: 當你像這樣呼叫 axios(config) 時,你實際上是在直接呼叫 Axios 物件本身。這個函式內部會處理配置 config,併發起請求。

  2. Axios 物件擁有方法 (HTTP verbs): axios.get(url[, config])axios.post(url[, data[, config]]) 等方法是 Axios 物件的屬性。這些方法是對 axios() 函式的封裝,它們預設了 HTTP 方法,並簡化了常見請求的呼叫方式。 例如,axios.get(url, config) 內部會呼叫 axios({...config, method: 'get', url})

  3. 函式過載 (透過引數型別判斷): axios() 函式內部會根據傳入引數的型別進行不同的處理。如果傳入的是一個配置物件 config,它會直接使用這個配置發起請求。如果傳入的是 URL 字串,它會將 URL 視為 config.url,並建立一個預設的 GET 請求配置。

// Simplified example of how axios might be implemented internally

function axios(configOrUrl, data, config) {
  let finalConfig = {};

  if (typeof configOrUrl === 'string') { // URL as first argument
    finalConfig.url = configOrUrl;
    finalConfig.method = 'get'; // Default to GET
    if (data) { // Second argument is data if provided
       finalConfig.data = data;
    }
    if (config) { // Third argument is config
      finalConfig = { ...finalConfig, ...config };
    }

  } else if (typeof configOrUrl === 'object') { // Config object as first argument
    finalConfig = { ...configOrUrl };
    if (data) {
      finalConfig.data = data; // Overwrite data if provided as second argument (less common)
    }
  } else {
    throw new Error('Invalid arguments provided to axios');
  }

  // ... rest of the axios logic to make the request using finalConfig
  return makeRequest(finalConfig);
}


// Adding HTTP verb methods to the axios object
axios.get = function(url, config) {
  return axios({ ...config, method: 'get', url });
};

axios.post = function(url, data, config) {
  return axios({ ...config, method: 'post', url, data });
};

// ... other HTTP verb methods (put, delete, patch, etc.)

// Example usage:

// Object style
axios({
  method: 'post',
  url: '/user/12345',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});

// Function style (GET)
axios('/user/12345').then(response => { /* ... */ });

// Function style (POST) - less common, can be confusing
axios('/user/12345', { firstName: 'Fred' }).then(response => { /* ... */ });


// Using convenience methods
axios.get('/user/12345').then(response => { /* ... */ });
axios.post('/user/12345', { firstName: 'Fred' }).then(response => { /* ... */ });

透過這種巧妙的設計,Axios 提供了靈活的 API,開發者可以根據自己的喜好和需求選擇不同的呼叫方式。 使用物件方式可以進行更精細的配置,而使用函式方式則更加簡潔方便。

相關文章