指数回退未返回承诺中的数据



我不确定我是否以正确的方式接近这一点。我已经尝试了几个不同版本的实现,但我把一个工作在这里,当backoff路径不使用。

那么,我有一个index.js,它就是:

import { Lizard } from './lizard.js';
const lizard = new Lizard();
const global_data = await lizard.global();
console.log(global_data);

在我的lizard.js中,我有一个函数类,但为了节省空间和噪音,我只会把那些重要的放在这里:

export class Lizard {
global() {
const path = '/global';
return this._request(path);
};
_buildRequestOptions(path, params) {
if (isObject(params)) params = querystring.stringify(params);
else params = undefined;
if (params == undefined) path = `/api/v${API_VERSION}${path}`;
else path = `/api/v${API_VERSION}${path}?${params}`;
// Return options
return {
path,
method: 'GET',
host: HOST,
port: 443,
timeout: Lizard.TIMEOUT,
};
};
async _request(path, params) {
const options = this._buildRequestOptions(path, params);
const maxRetries = 10;
function waitFor(milliseconds) {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
async function request(options, retries) {
if (retries > 0) {
const timeToWait = 15000 * retries;
console.log(`waiting for ${timeToWait}ms...`);
await waitFor(timeToWait);
}
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
let body = [];
res.on('data', (chunk) => {
body.push(chunk);
});
res.on('end', () => {
try {
body = Buffer.concat(body);
body = body.toString();
if (body.startsWith('<!DOCTYPE html>')) {
_WARN_('Invalid request', 'There was a problem with your request. The parameter(s) you gave are missing or incorrect.');
} else if (body.startsWith('Throttled')) {
_WARN_('Throttled request', 'There was a problem with request limit.');
}
body = JSON.parse(body);
} catch (error) {
reject(error);
};
const returnObject = ReturnObject(
!(res.statusCode < 200 || res.statusCode >= 300),
res.statusMessage,
res.statusCode,
body
)
if (returnObject.code != 429) {
resolve(returnObject);
} else {
if (retries < maxRetries) {
console.log('retrying...');
return request(options, retries + 1);
} else {
console.log("Max retries reached. Bubbling the error up");
resolve(returnObject);
}
}
});
});
req.on('error', (error) => reject(error));
req.on('timeout', () => {
req.abort();
reject(new Error(`Lizard API request timed out. Current timeout is: ${Lizard.TIMEOUT} milliseconds`));
});
// End request
req.end();
});
}
return await request(options, 0);
};
}

我试图用一种非常困难的方式做到这一点。对于其他可能偶然发现这一点的人,这里是我的最终解决方案:

lizard.js:

async function request(path, params, retries = 0, maxRetries = 10) {
let options = await buildRequestOptions(path, params);
return new Promise((resolve, reject) => {
let req = https.request(options, (res) => {
let body = [];
// Set body on data
res.on('data', (chunk) => {
body.push(chunk);
});
// On end, end the Promise
res.on('end', async () => {
try {
body = Buffer.concat(body);
body = body.toString();
// Check if page is returned instead of JSON
if (body.startsWith('<!DOCTYPE html>')) {
_WARN_('Invalid request', 'There was a problem with your request. The parameter(s) you gave are missing or incorrect.');
} else if (body.startsWith('Throttled')) {
_WARN_('Throttled request', 'There was a problem with request limit.');
}
// Attempt to parse
body = JSON.parse(body);
} catch (error) {
reject(error);
};
if (res.statusCode == 429 && retries < maxRetries) {
const timeToWait = 60000 + (1000 * retries);
console.error('Throttled request ' + retries + ' time(s)');
console.log(`Retrying in ${timeToWait}ms...`);
setTimeout(() => {
resolve(request(path, params, retries + 1));
}, timeToWait);
} else {
resolve(
objectify(
!(res.statusCode < 200 || res.statusCode >= 300),
res.statusMessage,
res.statusCode,
body
)
);
}
});
});
// On error, reject the Promise
req.on('error', (error) => reject(error));
// On timeout, reject the Promise
req.on('timeout', () => {
req.abort();
reject(new Error(`Lizard API request timed out. Current timeout is: ${TIMEOUT} milliseconds`));
});
// End request
req.end();
});
};

我仍然解决失败的对象,因为429是太多的请求,所以任何其他东西都需要冒泡。最重要的是,如果重试次数达到最大值,那么如果我看到429,我就知道我超过了。

最新更新