adapters.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import utils from '../utils.js';
  2. import httpAdapter from './http.js';
  3. import xhrAdapter from './xhr.js';
  4. import * as fetchAdapter from './fetch.js';
  5. import AxiosError from "../core/AxiosError.js";
  6. /**
  7. * Known adapters mapping.
  8. * Provides environment-specific adapters for Axios:
  9. * - `http` for Node.js
  10. * - `xhr` for browsers
  11. * - `fetch` for fetch API-based requests
  12. *
  13. * @type {Object<string, Function|Object>}
  14. */
  15. const knownAdapters = {
  16. http: httpAdapter,
  17. xhr: xhrAdapter,
  18. fetch: {
  19. get: fetchAdapter.getFetch,
  20. }
  21. };
  22. // Assign adapter names for easier debugging and identification
  23. utils.forEach(knownAdapters, (fn, value) => {
  24. if (fn) {
  25. try {
  26. Object.defineProperty(fn, 'name', { value });
  27. } catch (e) {
  28. // eslint-disable-next-line no-empty
  29. }
  30. Object.defineProperty(fn, 'adapterName', { value });
  31. }
  32. });
  33. /**
  34. * Render a rejection reason string for unknown or unsupported adapters
  35. *
  36. * @param {string} reason
  37. * @returns {string}
  38. */
  39. const renderReason = (reason) => `- ${reason}`;
  40. /**
  41. * Check if the adapter is resolved (function, null, or false)
  42. *
  43. * @param {Function|null|false} adapter
  44. * @returns {boolean}
  45. */
  46. const isResolvedHandle = (adapter) => utils.isFunction(adapter) || adapter === null || adapter === false;
  47. /**
  48. * Get the first suitable adapter from the provided list.
  49. * Tries each adapter in order until a supported one is found.
  50. * Throws an AxiosError if no adapter is suitable.
  51. *
  52. * @param {Array<string|Function>|string|Function} adapters - Adapter(s) by name or function.
  53. * @param {Object} config - Axios request configuration
  54. * @throws {AxiosError} If no suitable adapter is available
  55. * @returns {Function} The resolved adapter function
  56. */
  57. function getAdapter(adapters, config) {
  58. adapters = utils.isArray(adapters) ? adapters : [adapters];
  59. const { length } = adapters;
  60. let nameOrAdapter;
  61. let adapter;
  62. const rejectedReasons = {};
  63. for (let i = 0; i < length; i++) {
  64. nameOrAdapter = adapters[i];
  65. let id;
  66. adapter = nameOrAdapter;
  67. if (!isResolvedHandle(nameOrAdapter)) {
  68. adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()];
  69. if (adapter === undefined) {
  70. throw new AxiosError(`Unknown adapter '${id}'`);
  71. }
  72. }
  73. if (adapter && (utils.isFunction(adapter) || (adapter = adapter.get(config)))) {
  74. break;
  75. }
  76. rejectedReasons[id || '#' + i] = adapter;
  77. }
  78. if (!adapter) {
  79. const reasons = Object.entries(rejectedReasons)
  80. .map(([id, state]) => `adapter ${id} ` +
  81. (state === false ? 'is not supported by the environment' : 'is not available in the build')
  82. );
  83. let s = length ?
  84. (reasons.length > 1 ? 'since :\n' + reasons.map(renderReason).join('\n') : ' ' + renderReason(reasons[0])) :
  85. 'as no adapter specified';
  86. throw new AxiosError(
  87. `There is no suitable adapter to dispatch the request ` + s,
  88. 'ERR_NOT_SUPPORT'
  89. );
  90. }
  91. return adapter;
  92. }
  93. /**
  94. * Exports Axios adapters and utility to resolve an adapter
  95. */
  96. export default {
  97. /**
  98. * Resolve an adapter from a list of adapter names or functions.
  99. * @type {Function}
  100. */
  101. getAdapter,
  102. /**
  103. * Exposes all known adapters
  104. * @type {Object<string, Function|Object>}
  105. */
  106. adapters: knownAdapters
  107. };