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次后依然识别,就会结束请求。

posted @ 2025-09-21 15:43  dylan_bky  阅读(28)  评论(0)    收藏  举报