Promise中处理请求超时问题
1. 使用 Promise.race() 处理超时Promise
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<title>promise-ajax</title>
</head>
<body>
<script type="text/javascript">
// Create a timeout promise
function timeoutPromise(ms) {
return new Promise((_, reject) => {
setTimeout(() => reject(new Error('Request timeout')), ms);
});
}
// Fetch with timeout using Promise.race
async function fetchDataWithTimeout(url, timeout = 5000) {
try {
const response = await Promise.race([
fetch(url),
timeoutPromise(timeout)
]);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.text();
return data;
} catch (error) {
console.error('Fetch error:', error);
throw error;
}
}
// Usage
async function useWithTimeout() {
try {
const url = 'http://localhost:30000/test/slow';
const result = await fetchDataWithTimeout(url, 3000); // 3 second timeout
console.log('Result:', result);
} catch (error) {
if (error.message === 'Request timeout') {
console.error('Request timed out!');
} else {
console.error('Other error:', error);
}
}
}
useWithTimeout();
</script>
</body>
</html>
以上代码,设置超时时间为3秒,请求后3秒没有收到接口响应结果,就会结束请求。
2.使用 AbortController终止promise请求
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <title>promise-ajax</title> </head> <body> <script type="text/javascript"> async function fetchDataWithAbort(url, timeout = 5000) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), timeout); try { const response = await fetch(url, { signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.text(); return data; } catch (error) { clearTimeout(timeoutId); if (error.name === 'AbortError') { throw new Error('Request timeout'); } console.error('Fetch error:', error); throw error; } } // Usage async function useWithAbort() { try { const url = 'http://localhost:30000/test/slow'; const result = await fetchDataWithAbort(url, 3000); // 3 second timeout console.log('Result:', result); } catch (error) { if (error.message === 'Request timeout') { console.error('Request timed out!'); } else { console.error('Other error:', error); } } } useWithAbort(); </script> </body> </html>
同理,设置超时时间为3秒,请求后3秒没有收到接口响应结果,就会结束请求。
3.使用超时和重试次数来处理
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<title>promise-ajax</title>
</head>
<body>
<script type="text/javascript">
// Async function that returns a value
async function fetchWithRetryAndTimeout(url, options = {}) {
const {
timeout = 5000,
retries = 3,
retryDelay = 1000
} = options;
for (let i = 0; i <= retries; i++) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, {
signal: controller.signal,
...options
});
clearTimeout(timeoutId);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.text();
return data;
} catch (error) {
clearTimeout(timeoutId);
if (error.name === 'AbortError') {
throw new Error('Request timeout');
}
throw error;
}
} catch (error) {
console.log(`Attempt ${i + 1} failed:`, error.message);
if (i === retries) {
throw new Error(`Failed after ${retries + 1} attempts: ${error.message}`);
}
// Wait before retrying
await new Promise(resolve => setTimeout(resolve, retryDelay));
}
}
}
// Usage
async function useWithRetry() {
try {
const url = 'http://localhost:30000/test/slow';
const result = await fetchWithRetryAndTimeout(url, {
timeout: 3000,
retries: 3,
retryDelay: 1000
});
console.log('Result:', result);
} catch (error) {
console.error('Final error:', error.message);
}
}
useWithRetry();
</script>
</body>
</html>
以上代码,设置超时时间为3秒,请求间隔为1s,第一次请求失败后重试3次,如果重试3次后依然识别,就会结束请求。

浙公网安备 33010602011771号