如何从Axios获取响应时间

39

有人可以提供一些从Axios获取响应时间的方法吗?我发现了axios-timing,但我不是很喜欢它(有点争议,我知道)。我只是想知道是否还有其他人发现了一些记录响应时间的好方法。


开发工具中的网络选项卡怎么样? - Bk Santiago
这是自动化测试的一部分,因此需要在代码中。 - rozza
另一个答案:https://dev59.com/GLroa4cB1Zd3GeqPtORF#61712051 - Adarsh Madrecha
8个回答

64
您可以使用axios的拦截器概念。 请求拦截器会设置startTime。
axios.interceptors.request.use(function (config) {
 
  config.metadata = { startTime: new Date()}
  return config;
}, function (error) {
  return Promise.reject(error);
});

响应拦截器将设置结束时间并计算持续时间

axios.interceptors.response.use(function (response) {
 
  response.config.metadata.endTime = new Date()
  response.duration = response.config.metadata.endTime - response.config.metadata.startTime
  return response;
}, function (error) {
  error.config.metadata.endTime = new Date();
  error.duration = error.config.metadata.endTime - error.config.metadata.startTime;
  return Promise.reject(error);
});

1
如果您配置axios不正确,将会出现错误,但它不具有“error.config”,因此需要在设置endTime或duration之前检查错误方面是否已检查了“if(error.config){ }”。 - Loren
5
我看到了一个错误:类型“AxiosRequestConfig”上不存在属性“metadata”。 - patrick-fitzgerald
3
如果你遇到了一个错误信息 "Property 'metadata' does not exist on type ...",那么这意味着你正在使用 Typescript,并且在 AxiosRequestConfig 接口中确实不存在 metadata 属性。你可以定义一个新的接口来扩展 AxiosRequestConfig,并将配置强制转换为它,例如 (config as YourInterfaceWithMeta).metadata - Darkzarich
@patrick-fitzgerald,你先设置了'config.metadata'吗? - Sagar M
@patrick-fitzgerald。在Typescript中还有一种解决方案,可以使用config.data.metadata代替config.metadata。在这种情况下,您不需要像@DarkZ建议的那样定义新接口,因为data: any即可。 - Roman Kazanovskyi
显示剩余3条评论

23

这是我的解决方案,通过在拦截器中设置标题:

import axios from 'axios'

const url = 'https://example.com'

const instance = axios.create()

instance.interceptors.request.use((config) => {
    config.headers['request-startTime'] = process.hrtime()
    return config
})

instance.interceptors.response.use((response) => {
    const start = response.config.headers['request-startTime']
    const end = process.hrtime(start)
    const milliseconds = Math.round((end[0] * 1000) + (end[1] / 1000000))
    response.headers['request-duration'] = milliseconds
    return response
})

instance.get(url).then((response) => {
    console.log(response.headers['request-duration'])
}).catch((error) => {
    console.error(`Error`)
})

7

这里有另一种方法来实现:

const instance = axios.create() 

instance.interceptors.request.use((config) => {
  config.headers['request-startTime'] = new Date().getTime();
  return config
})

instance.interceptors.response.use((response) => {
  const currentTime = new Date().getTime()      
  const startTime = response.config.headers['request-startTime']      
  response.headers['request-duration'] = currentTime - startTime      
  return response
})

instance.get('https://example.com')
  .then((response) => {      
    console.log(response.headers['request-duration'])
  }).catch((error) => {
    console.error(`Error`)
  }) 

4

用 async/await 可以简单地实现这个功能,但并不是最理想的方式:

const start = Date.now()
await axios.get(url)
const finish = Date.now()

const time = (finish - start) / 1000

这将是axios调用的时间。虽然不太理想,但易于展示和实现。


3

@user3653268的基础上进行修改,以适用于React Hooks,并使用模数显示x.xxx秒。

import React, { useState } from 'react';
import axios from 'axios';

export default function Main() {
  const [axiosTimer, setAxiosTimer] = useState('');

  const handleSubmit = () => {
      let startTime = Date.now();
      axios.post('urlstuff')
      .then(response => {
          console.log('handleSubmit response: ', response);
          axiosTimerFunc(startTime);
      })
      .catch(err => {
          console.log("handleSubmit error:", err.response.data.message)
          axiosTimerFunc(startTime);
          setLoading(false);
      });
    }

  const axiosTimerFunc = (startTime) => {
    let now = Date.now();
    let seconds = Math.floor((now - startTime)/1000);
    let milliseconds = Math.floor((now - startTime)%1000);
    setAxiosTimer(`${seconds}.${milliseconds} seconds`);
  }

  return(
     <div>
        <h2>Load Time: {axiosTimer}</h2>
     </div>
  )
}

1
另一种简单的方法是:

axios.interceptors.response.use(
  (response) => {
    console.timeEnd(response.config.url);
    return response;
  },
  (error) => {
    console.timeEnd(error.response.config.url); 
    return Promise.reject(error);
  }
);

axios.interceptors.request.use(
  function (config) {
    console.time(config.url );
    return config;
}, function (error) {
    return Promise.reject(error);
});

2
直到您有两个同时请求相同的URL(可能甚至是不同的HTTP方法)。 - Kir

0

虽然时间已经过去很久,但这是我的简单解决方法

function performSearch() {
        var start = Date.now();
        var url='http://example.com';
        var query='hello';
        axios.post(url,{'par1':query})
            .then(function (res) {
                var millis = Date.now() - start;
                $('.timer').html(""+Math.floor(millis/1000)+"s")
            })
            .catch(function (res) {
                console.log(res)
            })


    }

这是我的解决方法


2
这看起来每个请求都需要这样做。使用拦截器作为捕获这个的更中心和优雅的方式,不是吗? - Dejan Vasic
我是这样做的,但是得到了负数时间 ;) - injecteer

-1

实际上,您可以通过从axios请求的响应中获取的“x-response-time”标头来获得它。

axios({
          method: 'GET',
          url: 'something.com',

        })
          .then((response) => {
            console.log(response.headers['x-response-time']);
          })

1
我没有看到这个,虽然它可能在后续版本中添加。你确定它不是服务器头吗? - fuzzyTew
我也没有这个问题,而且我正在使用最新的axios版本。 - Fels
我认为只有在服务器本身返回该标头时才可能实现。请纠正我。 - Omar Dulaimi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接