Last active
February 5, 2024 05:31
-
-
Save coodoo/77369d18b1767e71ce11510b85c3fcc6 to your computer and use it in GitHub Desktop.
替 fetch 加上 retry 與 timeout 功能
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
# goal | |
- 在不修改 node-fetch 原始參數格式下新增兩功能 | |
1. 新增 timeout 設定且逾時自動重試 | |
2. 新增 retry 模式可指定重試次數 | |
- 所有 config{} 皆有預設值因此使用上與原始 fetch() 相同 | |
- 目地是能無痛 drop-in replace 取代原始版 | |
# non-goal | |
- 改用 axios 或其它 fetch 套件 | |
- 原因是既有 codebase 內已大量使用 node-fetch 並備有完整測試 | |
- 此時更換套件風險太大故不為止 | |
*/ | |
async function fatch(url, options = {}, config = {}) { | |
if (config.retry_count === undefined) config.retry_count = 0 | |
let { | |
retries = 1, | |
delay = 30 * 1000, | |
timeout = 3 * 60 * 1000, | |
retry_count, | |
} = config | |
const controller = new AbortController() | |
options.signal = controller.signal | |
const tout = setTimeout(() => { | |
console.log(`[fatch] 連線逾時`, timeout) | |
controller.abort() | |
}, timeout) | |
return fetch(url, options) | |
.then(async (resp) => { | |
clearTimeout(tout) | |
return resp | |
}) | |
.catch(async (err) => { | |
clearTimeout(tout) | |
console.log(`\n[fatch] 炸掉`, { | |
url, | |
retry_count, | |
config, | |
ts: new Date().toLocaleString('en-US', { | |
timeZone: 'Asia/Taipei', | |
hour12: false, | |
}), | |
err: err.message, | |
}) | |
if (++config.retry_count <= retries) { | |
const time = config.retry_count * delay || 30 * 1000 | |
console.log(`[fatch] 重試等待時間`, `${time}ms`) | |
await exports.wait(time) | |
console.log(`[fatch] 啟動重試次數`, config.retry_count) | |
return fatch(url, options, config) | |
} else { | |
const msg = `fatch 重試 ${config.retry_count - 1} 次皆失敗,只好放棄` | |
const cause = { | |
url, | |
config, | |
err, | |
} | |
throw new Error(msg, { cause }) | |
} | |
}) | |
} | |
exports.wait = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment