Axios库中的超时功能无法正常工作。

86

我已经设置了axios.defaults.timeout = 1000;

我停止了提供API的服务器。

但是发送请求后超时需要超过1秒钟。

这是我的请求内容:

import axios from 'axios';
axios.defaults.timeout = 1000;

return axios.post(`${ROOT_URL}/login/${role}`, creds).then((response) => {
      console.log(response);

        if(response.status === 200) {
          // If login was successful, set the token in local storage
          localStorage.setItem(`${role}_log_toks`, JSON.stringify(response.data));

          // Dispatch the success action
          dispatch(receiveLogin(response.data));

          return response;
        }
      }).catch(err => {
        console.log(err);
        // If there was a problem, we want to
        // dispatch the error condition
        if(err.data && err.status === 404) {
          dispatch(loginError(err.data));
        } else {
          dispatch(loginError('Please check your network connection and try again.'));
        }

        return err;
      });

我也尝试过:

return axios.post(`${ROOT_URL}/login/${role}`, creds, {timeout: 1000}).then...
Axios不停止获取数据,5-10分钟后才显示网络错误。我知道有其他处理超时的技术,但为什么axios的超时功能不起作用呢?axios不停止获取数据的原因是什么?Axios版本0.9.1编辑: 如评论所述,我也尝试过:
import axios from 'axios';

const httpClient = axios.create();

httpClient.defaults.timeout = 500;

return httpClient.post(`${ROOT_URL}/login/${role}`, creds)
  .then(handleResponse)
7个回答

111

通过这个axios问题(感谢zhuyifan2013提供的解决方案),我发现axiostimeout响应超时而不是连接超时

假设你通过axios请求了URL,服务器需要很长时间才能响应,在这种情况下axios的超时设置将起作用。

但是如果你没有互联网连接或者请求的IP地址或域名不存在,那么axios的超时设置将不会起作用。

你需要使用其中一种axios取消方法 - cancelToken 例如:

const source = CancelToken.source();
const timeout = setTimeout(() => {
  source.cancel();
  // Timeout Logic
}, 10000);

axios.get(ip + '/config', {cancelToken: source.token}).then((result) => {
  // Clear The Timeout
  clearTimeout(timeout);

  // Handle your response
});
请注意,即使您有一个有效的连接,超时逻辑块仍将被执行。因此,您必须清除timeout

1
如果你在使用Angular时遇到了这个问题,你可以在可观察对象中添加.pipe(timeout(TIMEOUT_MILLIS))来解决。 - andrewgazelka
axios在浏览器环境中使用XMLHttpRequest,在没有网络连接的情况下会出现net::ERR_INTERNET_DISCONNECTED错误,因此我认为没有必要使用axios(或任何其他)超时。它仅适用于nodejs环境。浏览器可以做所有其他事情。因此,如果您真的想设置连接超时,可以尝试从axios获取请求对象并检查readyState - 直到它打开(1)- 还未连接。 - Mikhail Shemenyov
4
我不明白为什么他们不直接在库中实现这个功能,而是给我们一个有问题的超时选项。他们只是关闭了问题,没有修复它... - pguardiario
如果服务器关闭,axios的超时功能会起作用吗? - Irfan wani
2
我很感激@arthankamal提供的详尽答案。另一个选择是 Promise.race(axios.get(...), setTimeout(() => {}, 3000)),你也可以在axios请求中包含超时时间来单独捕获响应超时而非连接超时。 - Tee

41

这段代码对我有效:

axios({
  method: "post",
  url: 'http://example.com/api',
  timeout: 1000 * 5, // Wait for 5 seconds
  headers: {
    "Content-Type": "application/json"
  },
  data: {
    id: 1234
  }
})
  .then(response => {
    const serverResponse = response.data;
    // do sth ...
  })
  .catch(error => {
    console.log(error);
});

如果服务器在5秒内没有响应,它将进入catch块。

这也很有用:#1503


25

您需要创建axios HTTP客户端的实例:

const httpClient = axios.create();
httpClient.defaults.timeout = 500;

你可以按照以下方式使用httpClient:

return httpClient.post(`${ROOT_URL}/login/${role}`, creds)
  .then(handleResponse)

另外一件事是,您也可以在相同的配置中设置基本 URL 而不是使用${ROOT_URL}

httpClient.defaults.baseURL = ROOT_URL

2
  1. 我认为你想要返回httpClient.post(${ROOT_URL}/login/${role}, creds)。
  2. 我也尝试过这个,但没有成功。
  3. 目前,我正在使用mislav在这里提到的技术:https://github.com/github/fetch/issues/175 它非常好用,但我希望axios提供的超时功能能够起作用。
- shet_tayyy
我不确定为什么这对你不起作用。你使用的 axios 版本是什么?你能在上面包含你的 require / import 语句和 axios 初始化代码吗? - Clarkie

12

鸣谢 @arthankamal,因为他的回答是解决方案,这只是更新和跟进。

CancelToken 从 v0.22.0 开始弃用,因为他们改用 AbortController,所以我更新了他的代码。 详情请见:https://axios-http.com/docs/cancellation

TrySending(data) {
    let abortController = new AbortController()
    const timeout = setTimeout(() => {
        abortController.abort()
        console.log("Aborted")
    }, 3000)

    return axios
        .post(
            apiURL,
            data,
            { signal: abortController.signal }
        )
        .then(response => {
            clearTimeout(timeout)
            return true
        })
        .catch(error => false)
}

这将返回它是否成功执行。

一些注意事项:

  • 尝试使用 .finally 是不值得的,因为它不起作用
  • 如果被取消了,它将直接进入.catch(),并且错误将是 { message: 'canceled' }

9
submitHashtag = async () => {
  const data = await axios.post('/pwa/basics.php',  {
    withCredentials: true,// if user login
    timeout: 30000
  })
  if (!data) {
    // action here
    alert('reload window')
    return
  }
 }

虽然此链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会变得无效。-【来自审查】 - Daniel Cottone
@DanielCottone 请仔细审核。这也是一个答案。 - Zoe stands with Ukraine
它可以工作,但当我设置超时时间为999999时,会出现错误:“net :: ERR_CONNECTION_REFUSED”,而不是在设置超时时间大于5000时出现“超时时间超过999999ms”的错误。 - JillAndMe

0

0
这是一个关于指定网络错误超时requestTimeout的示例,使用async/await实现。

(改编自Fetch超时答案)

import axios from 'axios';
const requestTimeout = 2000; // how long to wait in case axios never connects
axios.defaults.timeout = 1000; // how long axios should wait for a response

async function axiosWithTimeout (options) {
  let reqTimeout; // make request timeout object available to both try and catch blocks 
  try {
    const controller = new AbortController();
    const signal = controller.signal;
    reqTimeout = setTimeout(() => controller.abort(), requestTimeout);
    const response = await axios({ signal, ...options });
    clearTimeout(reqTimeout); // we have an response, clear timeout
    return response;
  } catch (error) {
    clearTimeout(reqTimeout); // we have an error, clear timeout
    return error;
  }
}

axiosWithTimeout({
  // method, url, headers, params, etc for axios request
});

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