adapters.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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) =>
  47. utils.isFunction(adapter) || adapter === null || adapter === false;
  48. /**
  49. * Get the first suitable adapter from the provided list.
  50. * Tries each adapter in order until a supported one is found.
  51. * Throws an AxiosError if no adapter is suitable.
  52. *
  53. * @param {Array<string|Function>|string|Function} adapters - Adapter(s) by name or function.
  54. * @param {Object} config - Axios request configuration
  55. * @throws {AxiosError} If no suitable adapter is available
  56. * @returns {Function} The resolved adapter function
  57. */
  58. function getAdapter(adapters, config) {
  59. adapters = utils.isArray(adapters) ? adapters : [adapters];
  60. const { length } = adapters;
  61. let nameOrAdapter;
  62. let adapter;
  63. const rejectedReasons = {};
  64. for (let i = 0; i < length; i++) {
  65. nameOrAdapter = adapters[i];
  66. let id;
  67. adapter = nameOrAdapter;
  68. if (!isResolvedHandle(nameOrAdapter)) {
  69. adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()];
  70. if (adapter === undefined) {
  71. throw new AxiosError(`Unknown adapter '${id}'`);
  72. }
  73. }
  74. if (adapter && (utils.isFunction(adapter) || (adapter = adapter.get(config)))) {
  75. break;
  76. }
  77. rejectedReasons[id || '#' + i] = adapter;
  78. }
  79. if (!adapter) {
  80. const reasons = Object.entries(rejectedReasons).map(
  81. ([id, state]) =>
  82. `adapter ${id} ` +
  83. (state === false ? 'is not supported by the environment' : 'is not available in the build')
  84. );
  85. let s = length
  86. ? reasons.length > 1
  87. ? 'since :\n' + reasons.map(renderReason).join('\n')
  88. : ' ' + renderReason(reasons[0])
  89. : 'as no adapter specified';
  90. throw new AxiosError(
  91. `There is no suitable adapter to dispatch the request ` + s,
  92. 'ERR_NOT_SUPPORT'
  93. );
  94. }
  95. return adapter;
  96. }
  97. /**
  98. * Exports Axios adapters and utility to resolve an adapter
  99. */
  100. export default {
  101. /**
  102. * Resolve an adapter from a list of adapter names or functions.
  103. * @type {Function}
  104. */
  105. getAdapter,
  106. /**
  107. * Exposes all known adapters
  108. * @type {Object<string, Function|Object>}
  109. */
  110. adapters: knownAdapters,
  111. };