问题描述
我正在尝试围绕 Node HTTP/S module requests 编写一些包装器,而不使用 axios。 node-fetch 或任何其他 3rd 方模块。
例如,我想要函数 sendGet
、sendPost
、sendJSON
、sendFile
等。在理想情况下,这些函数将实现核心功能{{1 }},只是参数不同。
我希望每个包装器都返回一个承诺,这样调用者就可以对结果做任何事情。
所以想法是这样的。到目前为止,我能够制作一个包装器并通过承诺。但我无法添加重试失败的能力。它应该(在理想情况下)是 makeRequest
函数的一部分,但是当与 promise 结合时我无法这样做。谢谢你的想法
makeRequest
解决方法
试试这个,原来的函数现在叫做 tryRequest,外面有 for 循环来做重试
// core function
const makeRequest = async (method,url,retries = 0) => {
const tryRequest = async () => {
// returns reject on bad status
// returns resolve with body on successful request
return new Promise((resolve,reject) => {
const options = {method,};
const request = http.request(url,options,(response) => {
let chunks = [];
if (response.statusCode < 200 || response.statusCode >= 300) {
return reject('bad status code')
}
// collect data
response.on('data',(chunk => {
chunks.push(chunk)
}))
// resolve on end of request
response.on('end',() => {
let body = Buffer.concat(chunks).toString();
return resolve(body)
})
})
// reject on error of request (Service down)
request.on('error',function (error) {
reject(error);
})
request.end();
})
}
for (let i=1; i<=retries; i++) {
try {
console.log('Try No.',i);
url = url.substring(0,url.length - 1); // TODO To test,delete after it
return await tryRequest();
} catch(error) {
if (i < retries) continue;
throw error;
}
}
}
测试
await sendGet('http://example.com/abc',3); // Will work at the 3th try retry
await sendGet('http://example.xyz/abc',3); // Will fail server not found
,
您可以使用自定义承诺和 axios 或任何其他基于承诺的请求:
import { CPromise } from "c-promise2";
import cpAxios from "cp-axios";
const url =
"https://run.mocky.io/v3/7b038025-fc5f-4564-90eb-4373f0721822?mocky-delay=2s";
(async()=>{
const response= await CPromise.retry(() => cpAxios(url).timeout(5000));
})();
更复杂:
import { CPromise } from "c-promise2";
import cpAxios from "cp-axios";
const url =
"https://run.mocky.io/v3/7b038025-fc5f-4564-90eb-4373f0721822?mocky-delay=2s";
const promise = CPromise.retry(
(attempt) => {
console.log(`Attempt [${attempt}]`);
return cpAxios(url).timeout(attempt * 1000 + 500);
},{ retries: 3,delay: (attempt) => attempt * 1000 }
).then(
(response) => console.log(`Response: ${JSON.stringify(response.data)}`),(err) => console.warn(`Fail: ${err}`)
);
// promise.pause()
// promise.resume()
// promise.cancel()