[英]How to make HTTP request with promises and retries in Node.js
我正在尝试围绕Node HTTP/S 模块请求编写一些包装器,而不使用 axios。 node-fetch 或任何其他 3rd 方模块。
例如,我想要函数sendGet
, sendPost
, sendJSON
, sendFile
等。在理想情况下,这些函数将实现核心 function makeRequest
,只是使用不同的参数。
我希望每个包装器都返回一个 promise ,所以调用者可以对结果做任何事情。
我还希望包装器有一个参数,在失败的情况下请求重试多少次。
所以想法是这样的。 到目前为止,我能够制作一个包装器并通过 promise。 但我无法添加重试失败的能力。 它应该是(在理想情况下) makeRequest
function 的一部分,但是当与承诺结合使用时,我无法这样做。 谢谢你的想法
// intended usage of wrapper
sendGet('http://example.com', 3).then().catch()
// wrapper applies makeRequest fnc with various arguments
const sendGet = (url, retries) => {
return makeRequest('GET', url, retries)
}
const sendPost = (url, retries) => {
return makeRequest('POST', url, retries)
}
// core function
const makeRequest = async (method, url, retries = 0) => {
// returns reject on bad status
// returns resolve with body on successful request
return new Promise((resolve, reject) => {
const options = {/*method, hostname, etc */};
const request = http.request(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)
})
})
request.end();
})
}
试试这个,原来的 function 现在被称为 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
您可以使用自定义 promise 和 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()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.