【JavaScript】爆肝 2 万字!一次性搞懂 Ajax、Fetch 和 Axios 的区别~(下)

简介: 【JavaScript】爆肝 2 万字!一次性搞懂 Ajax、Fetch 和 Axios 的区别~(下)

4.3 响应处理

4.3.1 Axios

在 Axios 中,响应数据默认以 JSON 格式提供。我们所要做的就是访问响应对象的数据属性:

axios.get('https://fakestoreapi.com/products/1')
  .then(response => {
    console.log(response.data);
  }, error => {
    console.log(error);
  });

可以使用配置选项更改响应类型,即responseType属性。它指示服务器将响应的数据类型,选项包括:

  • arraybuffer
  • document
  • json (default)
  • text
  • stream
  • blob

4.3.2 Fetch

使用 Fetch,在访问响应数据之前我们还需要执行一个步骤:

fetch('https://fakestoreapi.com/products/1')
  .then((response) => response.json())
  .then((data) => {
    console.log(data);
  })
  .catch((error) => console.error(error));

微信图片_20230613145708.png使用fetch()时,我们会在所有标头到达后立即收到响应。 那时,我们还没有尚未加载的 HTTP 响应主体。 这就是我们收到另一个应许的原因。简而言之,response.json() 等待正文加载。

我们每天使用的 JSON 对象通常都比较小。但是,想象一下您必须加载非常大的图像的情况。这可能需要一段时间,在图像完全加载之前我们可能需要相关信息。

要阅读有关 response.json() 的更多信息,请查看此链接

4.3.2 总结

Fetch 是一个相对低级的 API,可以精确控制加载过程。 它伴随着每次使用它时必须处理两个 Promise 的成本。

  • Fetch 要求我们在处理响应时多做一步,因为它返回一个 Promise,此时我们没有我们需要的 JSON 数据格式,因此需要 .json() 方法。
  • 要在 Axios 中访问响应数据,我们使用 data 属性,而在使用 fetch() 时,最终数据可以命名为任何变量。

4.4 错误处理

还记得 AxiosFetch 都是基于 promiseHTTP 客户端吗?因此,他们都返回一个可以 resolverejectPromise。然而,就相似性而言,仅此而已—— promise得到 resolvereject 的条款大不相同。

4.4.1 Axios

让我们看一个典型的 Axios 错误处理示例,使用 .catch()

axios.get('https://codilime.com/')
  .then(response => console.log(response.data))
  .catch((err) => console.log(err.message));

每个响应都包含一个状态属性,它只是一个 HTTP 响应状态代码。这些代码表示请求是否已成功完成。例子包括:

  • 200 OK - 请求成功,
  • 403 Forbidden——客户端无权访问内容,
  • 418 I'm a teapot - 服务器拒绝尝试用茶壶冲泡咖啡(不,这不是玩笑,请在此处查看)。

可以在此处阅读有关这些 HTTP 响应状态代码的更多信息。

现在我们知道了 HTTP 响应状态代码是什么,我们可以理解 Axios 错误处理是如何工作的。Axios 将拒绝任何状态码超出 200-299 范围(成功响应)的Promise

我们可以检查错误对象以获取有关错误的更多信息:

axios.get('https://fakestoreapi.com/products/1')
  .then(response => console.log(response.data))
  .catch((err) => {
    if (err.response) {
      // The request was made, but the server responded with a status code that falls out of the 2xx range
      const { status } = err.response;
      if (status === 401) {
        // The client must authenticate itself to get the requested response
      }
      else if (status === 502) {
        // The server got an invalid response
      }
      ...
    }
    else if (err.request) {
      // The request was made, but no response was received
    } 
    else {
      // Some other error
    }
  });

当我们在错误对象上有 response 属性时,这意味着发出了请求,并且服务器响应了,但是响应状态代码在2xx 范围之外。另一方面,请求属性表示已发出请求,但未收到响应。如果这两者都不正确,则表示设置网络请求时出现问题,从而触发错误。

4.4.2 Fetch

获取错误处理与 Axios 有很大不同。最重要的区别是,如果我们收到 HTTP 错误,它不会reject Promise——不成功的响应仍然会得到解决。因此,HTTP 错误在 .then 块中处理。只有在网络出现故障的情况下,Fetch API Promise才会被拒绝。

fetch('https://fakestoreapi.com/products/1')
  .then(response => {
    if (!response.ok) {
      throw Error(`HTTP error: ${response.status}`);
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch((error) => {
    console.log(error)
  });

使用 Fetch API 需要我们检查response.ok属性来控制 HTTP 错误。

两个最重要的响应属性是statusok

  • status - 响应状态代码(整数)。
  • ok - 检查状态是否在 2xx(布尔值)范围内的简写。

在成功的场景中,它们将分别具有200true值:

{
  ...
  status: 200,
  ok: true,
  ...
}

但是,在错误情况下,我们将获得 HTTP 错误状态代码和false。例如,如果我们没有通过身份验证来接收请求的响应,我们将得到:

{
  ...
  status: 401,
  ok: false,
  ...
}

4.4.3 总结

在 Axios 中,超出 200-299 范围(成功响应)的响应将被自动拒绝。使用 .catch() 块,我们可以获得有关错误的信息,例如是否收到响应,如果收到,则返回其状态代码。

另一方面,在 fetch() 中,不成功的响应仍然得到解决。这就是为什么我们必须检查响应的ok属性并在它设置为 false 时抛出错误。然后在.catch() 块中处理该错误。

4.5 响应超时

在设定的时间后中止请求的功能是发出 HTTP 请求的重要部分。如果没有该功能,请求可能会挂起并可能导致我们的应用程序变慢。

4.5.1 Axios

使用 Axios 设置响应超时非常容易。我们所要做的就是在请求的配置对象中添加一行:

axios.get(url, {
  ...
  timeout: 2000,
  ...
})
  .then(response => console.log(response.data))
  .catch(err => console.log(err.message))

超时是一个可选参数,以毫秒为单位。如果超过两秒,上述请求将被中止,并记录错误。timeout属性的默认值为0,表示没有超时。

4.5.2 Fetch

用 Fetch API 做同样的事情并不容易。要实现相同的行为,我们可以使用名为AbortController的接口和fetch() 方法配置选项:

const controller = new AbortController();
const options = {
  method: 'POST',
  signal: controller.signal,
  body: JSON.stringify({
    firstName: 'David',
    lastName: 'Pollock'
  })
};  
const promise = fetch('/login', options);
const timeoutId = setTimeout(() => controller.abort(), 4000);
promise
  .then(response => {/* handle the response */})
  .catch(error => console.error('timeout exceeded'));

在这里,通过创建一个AbortController对象,我们可以访问abort() 方法和信号对象,它允许我们稍后中止该请求。信号是 AbortController 的一个只读属性,提供了一个与请求沟通或中止请求的方法。如果服务器在四秒内没有回应,controller.abort() 就会被调用,操作就会终止。

请注意,如果您在fetch() 完成后调用*abort() ,它只会忽略它。

4.5.3 总结

fetch() 没有像 Axios 那样为我们提供超时配置选项。相反,我们必须使用AbortController接口和setTimeout函数。Axios 隐藏了很多这样的样板文件,这使其成为大多数用例的明显赢家。 但是,我们已经知道 Fetch 是一个低级 API。根据您的需要,在响应超时和取消请求方面,您可能仍然更喜欢 Fetch 而不是 Axios。

4.6 HTTP 请求和响应拦截

Axios 的主要功能之一是其拦截 HTTP请求 的能力。当你需要检查或改变从你的应用程序到服务器的HTTP请求或反之亦然时,HTTP拦截器就会派上用场(例如,记录、认证或重试一个失败的HTTP请求)。

有了拦截器,你就不必为每个HTTP请求单独编写代码。当你想为你处理请求和响应的方式设置一个全局策略时,HTTP拦截器很有帮助。

想象一个场景,我们必须保存从我们的应用程序发送的每个 HTTP 请求的日志。向每个请求添加这样的代码很麻烦,容易出错,简而言之,不可行。这就是拦截器发挥作用的时候。它们允许我们消除为每个请求重复代码,而是创建和设置处理请求和响应的全局行为。

简而言之,HTTP 拦截器用于在客户端和服务器端 HTTP 请求和响应之间应用自定义逻辑。它们可用于不同的操作,例如:

  • 修改 HTTP 标头或正文
  • 设置自定义令牌
  • 修改响应

4.6.1 Axios

Axios 具有用于简单创建 HTTP 拦截器的功能 - 包括响应和请求拦截器。首先,让我们看一个请求拦截器:

axios.interceptor.request.use(config => {
  // log data before HTTP request is sent
  console.log('HTTP request being sent...');
  return config;
})

上面的代码会在发送任何 HTTP 请求之前产生一条日志消息。类似地,响应拦截器被定义为在它们被thencatch处理之前运行一些代码:

axios.interceptor.response.use(
  function (response) {
    // This function will be triggered on any status code inside 2xx range
    return response;
  },
  function (error) {
    // This function will be triggered on any status code outside of 2xx range
    return Promise.reject(error);
  }
)

例如,当您想要设置一个策略以在失败的情况下始终重试一次 HTTP 请求时,响应拦截器可能会派上用场。

如果您愿意,Axios 还允许您删除拦截器:

const requestInterceptor = axios.interceptor.request.use(config => {
  // log data before HTTP request is sent
  console.log('HTTP request being sent...');
  return config;
});
axios.interceptor.request.eject(requestInterceptor);

4.6.2 Fetch

使用 Fetch API 时,我们没有配置选项或特殊的内置函数来实现拦截器。然而,Vanilla JS(一种快速、轻量级、跨平台的框架)就足够了:

fetch = (originalFetch => {
  return (...arguments) => {
    const result = originalFetch.apply(this, arguments);
    return result.then(console.log('HTTP request being sent ...'));
  };
})(fetch);

上面的代码是一个 HTTP 请求拦截器的实现。我们可以像使用普通的旧fetch() 函数一样使用它:

fetch('https://fakestoreapi.com/products/1')
  .then(response => response.json())
  .then(console.log)

4.6.3 总结

Axios 为我们提供了开箱即用的功能来创建 HTTP 请求和响应拦截器。 与响应超时类似,它隐藏了大部分样板文件并为我们提供了一个漂亮、易于使用的界面。

另一方面,我们有 Fetch API,同样因为它的级别低,没有为我们提供这样的方法。基于 fetch() 的 HTTP 拦截器很容易编写,并且可以在 Internet 上找到

再一次,我们可以选择避免样板文件而不是更细粒度的控制和自定义选项。选择应基于用例和个人需求。

4.7 download 进度

在 XMLHttpRequests 仍然被广泛使用的日子里,它是用于实现进度指示器的.onprogress 方法。今天,这些指标仍然是加载资产的重要组成部分,尤其是大资产,尤其是对于互联网连接速度较慢的用户。但是,我们不必再摆弄这个接口了。

让我们下载一张图片!

4.7.1 Axios

在使用axios库的时候,一般会使用axios Progress Bar来实现一个进度条。

它可以通过 NPM 包获得:

npm install --save axios-progress-bar

或者通过 CDN:

<script src="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/index.js"></script>

之后,我们需要将 CSS 导入到 HTML 中,或者通过带有模块打包器的 JavaScript,例如webpack

<link rel="stylesheet" type="text/css" href="https://cdn.rawgit.com/rikmms/progress-bar-4-axios/0a3acf92/dist/nprogress.css" />

就是这样的设置。现在我们可以实现进度条了。我们必须(仅一次)调用loadProgressBar() 函数,该函数可选择采用两个参数 - config 和 instance。配置对象的属性可以在这里看到。第二个参数用于传递自定义 axios 实例。现在,我们将跳过这两个参数以使其尽可能简单。

...
<img id="codilime-logo" />
...
<script type="text/javascript">
  loadProgressBar();
  const url = 'http://codilime.com/image/path/logo.jpg';
  function downloadFile(url) {
    axios.get(url, {
      responseType: 'blob',
    })
      .then(response => {
        const fileReader = new window.FileReader();
        fileReader.readAsDataURL(response.data);
        fileReader.onload = () => {
          document.getElementById('codilime-logo').setAttribute('src', fileReader.result);
        };
      })
      .catch(error => {
        console.log(error)
      })
  }
  downloadFile(url);
</script>

上面的代码使用了FileReader API它允许我们使用FileBlob对象读取文件的内容。FileReader.readAsDataURL()开始读取指定blob的内容,完成后,FileReader.result属性包含一个编码字符串。我们还使用了load事件,它会在读取成功完成时触发。那是我们将结果插入元素中的src属性的时候。

Axios 进度条设计基于angular-loading-bar。它使用负责在浏览器中显示加载栏的nprogress模块。

4.7.2 Fetch

使用 Fetch API 实现进度条并不容易,我们没有像 Axios 那样为我们提供简单易用 API 的包。不过不要害怕 - 正如你可能猜到的那样,还有另一个低级 API 允许我们实现进度条。可悲的是,有更多的代码。

我们将使用ReadableStream API。这个接口代表一个可读的字节数据流。此外,ReadableStream实例存在于Response 对象body属性中。我们将使用该字节流来跟踪进度。

HTML 文件:

...
<div id="progress-bar" src="">Progress bar</div>
<img id="codilime-logo" />
...

文件:

const el = document.getElementById('progress-bar');
fetch('http://codilime.com/image/path/logo.jpg')
  .then(response => {
    if (!response.ok) {
      throw Error(`HTTP error: ${response.status}`);
    }
    // Ensure ReadableStream is supported
    if (!response.body) {
      throw Error('ReadableStream API is not supported in this browser');
    }
    // The Content-Length header indicates the size of the message body, in bytes
    const contentLength = response.headers.get('content-length');
    if (!contentLength) {
      throw Error ('Content-Length response header unavailable');
    }
    const total = parseInt(contentLength, 10);
    let loaded = 0;
    return new Response(
      new ReadableStream({
        start(controller) {
          const reader = response.body.getReader();
          read();
          // read() function handles each data chunk
          function read() {
            reader.read().then(({ done, value }) => {
              // No more data to read
              if (done) {
                controller.close();
                return;
              }
              loaded += value.byteLength;
              progress({ loaded, total });
              // Get the data and send it to the browser via the controller
              controller.enqueue(value);
              read();
            }).catch(error => {
              console.error(error);
              controller.error(error);
            })
          }
        }
      })
    );
  })
  .then(response => response.blob())
  .then(data => {
    document.getElementById('codilime-logo').src = URL.createObjectURL(data);
  })
  .catch(error => {
    console.error(error);
  })
  function progress({ loaded, total }) {
    el.innerHTML = Math.round(loaded / total * 100) + '%';
  }

好的,这是很多代码 - 让我们一步一步地完成它。

<div id="progress-bar" src="">Progress bar</div>
<img id="codilime-logo" />

在 HTML 文件中,我们创建一个img标签,与 Axios 示例中的相同。此外,我们必须创建一个div作为我们的进度条,我们不使用外部包,所以我们必须自己创建它。

const el = document.getElementById('progress-bar');
fetch('http://codilime.com/image/path/logo.jpg')
  .then(response => {
    if (!response.ok) {
      throw Error(`HTTP error: ${response.status}`);
    }
    // Ensure ReadableStream is supported
    if (!response.body) {
      throw Error('ReadableStream API is not supported in this browser');
    }
    // The Content-Length header indicates the size of the message body, in bytes
    const contentLength = response.headers.get('content-length');
    if (!contentLength) {
      throw Error ('Content-Length response header unavailable');
    }
...

然后进入 JS。我们将div元素保存在 el变量中。之后,我们提出请求。标准程序是检查是否存在任何 HTTP 错误、是否支持 ReadableStream API,以及是否存在 Content-Length 标头。

所有主流浏览器都支持 ReadableStream API,您可以通过caniuse检查。因此,您可以在实现中省略第二个 if 语句。

我们添加第三个 if 语句,因为要访问标头,服务器必须发送 CORS 标头 - Access-Control-Expose-Headers - “Access-Control-Expose-Headers: content-length”。此响应标头允许服务器指示哪些响应标头应提供给浏览器中运行的脚本,以响应跨域请求。

现在,进入返回的响应。

...
const total = parseInt(contentLength, 10);
let loaded = 0;
return new Response(
  new ReadableStream({
    start(controller) {
...

ReadableStream 构造函数从给定的处理程序创建并返回一个可读流对象。它接受underlayingSourceobject,其中包含定义构造流实例行为方式的方法和属性。您可以在此处阅读更多信息。

在我们的例子中,我们唯一需要的是start(controller) 方法。构造对象时立即调用它。它的内容应该旨在访问流源和设置流功能。控制器属性ReadableStreamDefaultControllerReadableByteStreamController,具体取决于类型属性。

...
const reader = response.body.getReader();
...

ReadableStreamgetReader()方法创建一个读取器并将流锁定到它。在该锁定期间,在释放此读取器之前,无法获取其他读取器。

...
read();
// read() function handles each data chunk
function read() {
  reader.read().then(({ done, value }) => {
    // No more data to read
    if (done) {
      controller.close();
      return;
    }
    loaded += value.byteLength;
    progress({ loaded, total });
    // Get the data and send it to the browser via the controller
    controller.enqueue(value);
    read();
  }).catch(error => {
    console.error(error);
    controller.error(error);
  })
}
...

read() 函数中,我们调用 readerread() 方法,它返回一个Promise,提供对流内部队列中下一个块的访问。 如果块可用,Promise将通过以下形式的对象实现:

{
  value: theChunk,
  done: false,
}

否则,如果流关闭,Promise将通过以下形式的对象实现:

{
  value: undefined,
  done: true,
}

只有当流显示错误时,promise 才会被 reject

...
// No more data to read
if (done) {
  controller.close();
  return;
}
loaded += value.byteLength;
progress({ loaded, total });
// Get the data and send it to the browser via the controller
controller.enqueue(value);
read();
...

如果没有更多数据要读取,我们使用close()方法关闭关联的流。否则,我们使用进度函数修改div元素。之后,我们使用enqueue() 函数将给定块排入关联流中。

...
console.error(error);
controller.error(error);
...

.catch 子句中,我们使用 error() 方法,这会导致未来与关联流的任何交互出错。

请记住,这只是使用 Fetch API 实现进度条的一种方式。您可以在此GitHub 存储库中查看此实现和其他实现。

4.7.3 总结

这是和以前一样的故事。我们有一个选择。对于高级 Axios API,我们必须使用一个额外的包—— Axios Progress Bar

另一方面,我们有低级的 Fetch API,我们也可以在其中实现进度条。更重要的是,我们可以用各种不同的方式来实现它。这肯定是更多的代码,而且,像往常一样,它提供了对数据处理每个阶段发生的事情的更细粒度的控制。最重要的是,我们不需要任何额外的包。这一切都可以只用 JavaScript 和一些 API 来完成。

4.8 并行请求

如果您已经完成了进度条部分,您会很高兴听到 AxiosFetch API 都提供了易于使用的方式来同时发出多个请求。让我们看看它的实际效果。

4.8.1 Axios

在 Axios 中,我们创建了一个请求数组。每个请求的创建方式与以前相同。此外,我们使用axios.all方法发出多个 HTTP 请求:

const endpoints = [
  'https://fakestoreapi.com/products/1',
  'https://fakestoreapi.com/products/2',
  'https://fakestoreapi.com/products/3'
];
axios.all(
  endpoints.map(endpoint => axios.get(endpoint))
).then(console.log)

我们通过每个端点进行映射,向当前端点发出HTTP GET请求

axios.all 返回一个数组作为响应,其中每个条目对应于我们的端点数组中的一个端点。因此,我们将在data[0]处获得endpointcodilime.com/endpoint1的响应,在data[1]处获得 codilime.com/endpoint2 等的响应。

值得庆幸的是,Axios 还提供了axios.spread方法,它的行为类似于常规的 JavaScript 展开运算符 -  ...

const endpoints = [
  'https://fakestoreapi.com/products/1',
  'https://fakestoreapi.com/products/2',
  'https://fakestoreapi.com/products/3'
];
axios.all(
  endpoints.map(endpoint => axios.get(endpoint))
)
  .then(axios.spread((res1, res2, res3) => {
    console.log(res1.data, res2.data, res3.data);
  }))

4.8.2 Fetch

使用 Fetch API 时,我们可以使用 Promise.all() 方法和解构实现类似的行为:

js

复制代码

const endpoints = [
  'http://codilime.com/endpoint1',
  'http://codilime.com/endpoint2',
  'http://codilime.com/endpoint3',
];
Promise.all(
  endpoints.map(endpoint => fetch(endpoint))
)
  .then(async ([ res1, res2, res3 ]) => {
    const res1JSON = await res1.json();
    const res2JSON = await res2.json();
    const res3JSON = await res3.json();
    console.log(res1JSON, res2JSON, res3JSON);
  }))

如果您不熟悉Promise.all(),它会接受可迭代的Promise(例如数组)并返回单个Promise,该Promise解析为输入Promise结果的数组。

4.8.3 总结

在同时发出多个请求时,我们有两个非常相似的解决方案。一种利用外部库方法,另一种使用内置 JavaScript 方法。但是,这两个实现的含义和流程几乎相同。

5、总结

  1. 底层实现:Ajax 的底层实现使用了浏览器内置的 XMLHttpRequest(XHR) 对象,使用方式相对繁琐;而 Fetch API 则使用了基于 Promisefetch() 函数。Axios 则是基于 XHRnode.jshttp 封装的库。
  2. 兼容性:Ajax 具有较好的兼容性,几乎可以在所有浏览器上运行。FetchAxios 虽然也具有较好的兼容性,但需要考虑到浏览器版本和功能支持问题,需要使用 polyfill 或其他兼容性解决方案来保证兼容性。
  3. Promise 和回调函数:Ajax 不支持 Promise,通常使用回调函数来处理异步请求的结果,这种方式容易出现回调地狱的情况;FetchAxios 则使用 Promise 对象来处理异步请求的结果,可以更加方便地进行链式调用和错误处理。
  4. 浏览器支持:AjaxXHR 对象在旧版浏览器中的支持存在一些问题;Fetch API 是比较新的标准,可能会存在一些兼容性问题;Axios 则是一个基于 Promise 的库,支持各种现代浏览器和 Node.js 环境。
  5. 功能和扩展性:AjaxXHR 对象提供了基本的请求和响应功能,但是缺乏灵活性和扩展性。Fetch API 则提供了更加丰富的请求和响应选项,支持请求和响应的拦截、转换、缓存等功能。Axios 则在 Fetch API 的基础上提供了更加强大和灵活的功能,如请求和响应的取消、并发、批量处理等。
  6. 请求和响应拦截器:Axios 支持请求和响应拦截器,可以在请求或响应被处理前或后进行操作,比如添加请求头、修改响应数据等。这对于需要对请求或响应进行全局处理的场景非常有用。FetchAjax 相比较没有内置的请求和响应拦截器,需要手动编写实现。
  7. 库的大小和性能:AjaxXHR 对象是浏览器内置的 API,不需要引入额外的库,因此体积较小,但是在处理大量请求时性能可能较差。Fetch API 是新的标准,需要使用 polyfill 或者引入额外的库,因此体积较大,但是性能相对较好。Axios 是一个功能丰富的库,体积相对较大,但是性能表现较好,尤其在处理大量请求时优势更为明显。
  8. 并发请求:Axios 可以方便地发送多个并发请求,通过 Promise.allPromise.race 来处理响应。而 FetchAjax 只能通过 Promise 来处理单个请求,需要手动编写实现并发请求的逻辑。
  9. 对于同源策略的处理:AjaxFetch API 都遵循浏览器的同源策略,不能直接请求不同域名的资源。但是,它们可以通过设置 CORS 或使用 JSONP 等技术来实现跨域请求。而 Axios 对跨域请求的处理更为简单,可以通过使用代理等方式来实现跨域请求。
  10. 请求的取消和超时:Axios 支持请求的取消和超时设置,可以在发送请求时设置 cancelTokentimeout 选项,对于需要及时取消或超时的请求非常有用。Fetch APIAjax 在原生状态下不支持请求的取消和超时设置,需要手动编写实现。
  11. API 的使用风格:AjaxFetchAxiosAPI 的使用风格上有所差异。Ajax 使用的是回调函数的方式,代码结构较为混乱,不易维护。Fetch API 使用 Promise 的方式,代码结构清晰、易读、易维护。而 Axios 同样使用 Promise 的方式,但相对于 Fetch API 来说,它的 API 更为灵活,可以方便地进行扩展和定制。
  12. 使用场景:AjaxFetchAxios 在不同的使用场景下有不同的优势。Ajax 的优势在于它是原生的浏览器 API,功能简单、易用、兼容性好,适合简单的异步请求场景。Fetch API 的优势在于它是 Promise 风格的 API,支持流式传输、文件上传和下载等功能,适合复杂的异步请求场景。而 Axios 的优势在于它是一个功能齐全、易用、灵活的请求库,支持请求和响应拦截器、请求的取消和超时、并发请求等功能,适合复杂的异步请求场景。
Ajax Fetch API Axios
基于Promise 🛑(基于 XMLHttpRequest)
兼容性 ✅ 具有较好的兼容性,几乎可以在所有浏览器上运行 🟡 对于现代浏览器的兼容性更好 🟡 对于现代浏览器的兼容性更好
TypeScript支持 🛑 🟡
数据缓存 🛑
自动重试 🛑
取消请求 🟡 原生不支持,需手动编写实现 🟡 原生不支持,需手动编写实现
请求异常 🟡 在网络异常和超时处理方面需要手动编写实现 🟡 在网络异常和超时处理方面需要手动编写实现 ✅ 提供了更好的网络异常处理机制,可以方便地处理网络异常和超时异常
超时时间 🛑 🛑
跨域 🟡 原生不支持跨域请求,需手动实现(如JSONP)
错误处理 🟡 原生对于错误处理和状态码处理的支持相对较少 🟡 原生对于错误处理和状态码处理的支持相对较少 ✅ 提供了丰富的错误处理和状态码处理的功能
请求响应拦截 🛑 🟡 ✅(全局)
并发请求 🟡 原生不支持并发请求,需要手动编写实现
数据转换 🟡 原生状态下需要手动将响应数据转换为 JavaScript 对象 🟡 原生状态下需要手动将响应数据转换为 JavaScript 对象 ✅ 可以自动将响应数据转换为 JavaScript 对象
序列化参数 ✅ 使用 URLSearchParams 🟡 原生不支持 URLSearchParams 对象,需要手动编写实现 ✅ 使用 URLSearchParams
文件处理 🟡 原生不支持文件上传和下载,需要手动编写实现 🟡 原生不支持文件上传和下载,需要手动编写实现
插件机制 🟡 在扩展性方面相对较差,需要手动编写实现 🟡 在扩展性方面相对较差,需要手动编写实现 ✅ 支持自定义拦截器、转换器、扩展请求和响应等功能
数据格式 🟡 对数据格式的支持相对较少,需要手动编写实现 🟡 对数据格式的支持相对较少,需要手动编写实现 ✅ 支持多种数据格式的请求和响应,包括 JSON、URL-encoded、XML、HTML、Text 等
headers验证 🛑 ✅ 支持通过 request.credentials 属性来控制请求是否携带 cookies 和 cors 相关的头部信息 ✅ 可以使用 withCredentials 配置选项来控制请求是否携带 cookies 和 cors 相关的头部信息



相关文章
|
2月前
|
前端开发 API UED
Python后端与前端交互新纪元:AJAX、Fetch API联手,打造极致用户体验!
Python后端与前端交互新纪元:AJAX、Fetch API联手,打造极致用户体验!
94 2
|
10天前
|
数据采集 前端开发 JavaScript
虎扑APP数据采集:JavaScript与AJAX的结合使用
虎扑APP数据采集:JavaScript与AJAX的结合使用
|
15天前
|
前端开发 API 开发者
Python Web开发者必看!AJAX、Fetch API实战技巧,让前后端交互如丝般顺滑!
在Web开发中,前后端的高效交互是提升用户体验的关键。本文通过一个基于Flask框架的博客系统实战案例,详细介绍了如何使用AJAX和Fetch API实现不刷新页面查看评论的功能。从后端路由设置到前端请求处理,全面展示了这两种技术的应用技巧,帮助Python Web开发者提升项目质量和开发效率。
30 1
|
1月前
|
XML 前端开发 JavaScript
详解Ajax与axios的区别
详解Ajax与axios的区别
|
1月前
|
前端开发 API 开发者
深度剖析:AJAX、Fetch API如何成为Python后端开发者的最佳拍档!
深度剖析:AJAX、Fetch API如何成为Python后端开发者的最佳拍档!
38 4
|
1月前
|
前端开发 JavaScript API
惊呆了!学会AJAX与Fetch API,你的Python Web项目瞬间高大上!
在Web开发领域,AJAX与Fetch API是提升交互体验的关键技术。AJAX(Asynchronous JavaScript and XML)作为异步通信的先驱,通过XMLHttpRequest对象实现了局部页面更新,提升了应用流畅度。Fetch API则以更现代、简洁的方式处理HTTP请求,基于Promises提供了丰富的功能。当与Python Web框架(如Django、Flask)结合时,这两者能显著增强应用的响应速度和用户体验,使项目更加高效、高大上。
50 2
|
1月前
|
前端开发 API 开发者
从零到精通,AJAX与Fetch API让你的Python Web前后端交互无所不能!
从零到精通,AJAX与Fetch API让你的Python Web前后端交互无所不能!
43 3
|
1月前
|
前端开发 API 数据格式
颠覆传统!AJAX、Fetch API与Python后端,开启Web开发新篇章!
在Web开发领域,技术的快速迭代推动着应用不断进化。传统前后端交互方式已无法满足现代Web应用对高效、实时性和用户体验的需求。AJAX作为异步通信的先驱,使页面无需刷新即可更新部分内容,显著提升用户体验;尽管XML曾是其主要数据格式,但如今JSON已成为主流。Fetch API则以其简洁、灵活的特点成为AJAX的现代替代品,基于Promises的异步请求让开发更加高效。与此同时,Python后端凭借高效稳定和丰富的库支持,成为众多开发者的首选,无论是轻量级的Flask还是全功能的Django,都能为Web应用提供强大的支撑。
37 0
|
1月前
|
XML 前端开发 API
惊艳全场的秘诀!AJAX、Fetch API与Python后端,打造令人惊叹的Web应用!
惊艳全场的秘诀!AJAX、Fetch API与Python后端,打造令人惊叹的Web应用!
26 0
|
1月前
|
前端开发 JavaScript API
告别繁琐!AJAX与Fetch API,让你的前后端沟通畅通无阻,项目效率飙升!
在Web开发中,前后端的顺畅沟通至关重要。传统方法常需频繁刷新页面,影响体验与效率。AJAX和Fetch API的出现简化了这一过程。AJAX利用XMLHttpRequest实现局部页面更新,提升用户体验;Fetch API则以更简洁的语法和强大的功能,进一步优化异步请求处理。两者均能显著提高开发效率,简化代码结构,让项目迭代更快速。拥抱这些技术,让Web开发之路更加顺畅。
26 0