我在为序列化API请求并确保当前未请求端点的requestHandler中实现了递归函数。为了确保当前未请求该端点,我将其添加到Set并使用条件进行验证。
问题在于,当对同一端点发出大量请求时,此递归方法会消耗大量内存。有什么办法可以使它同时减少内存密集性和性能?我很想听听可以替代递归使用的任何其他方法。在下面可以找到我的代码。
async request(endpoint, domain, method, headers, query, body, attachments) {
const requestURL = `${(domain === "discord") ? this.discordBaseURL :
(domain === "trello") ? this.trelloBaseURL : domain}/${endpoint}`;
if (this.queueCollection.has(endpoint) === false) { // queueCollection is the Set in which I store endpoints that are currently being requested by my requestHandler.
this.queueCollection.add(endpoint);
const response = await this.conditionalsHandler(endpoint, requestURL, method, headers, query, body, attachments);
this.queueCollection.delete(endpoint);
return response;
}
else {
const response = new Promise((resolve) => {
setTimeout(() => { // https://stackoverflow.com/a/20999077
resolve(this.request(endpoint, domain, method, headers, query, body, attachments)); // This is where I make the method recursive to call itself back until the endpoint is no longer in the queueCollection Set.
}, 0);
});
return response;
}
}
答案 0 :(得分:-1)
是的,您可以通过将queueCollection
设为Map<string, Promise>
而不是Set<string>
来删除递归,而不是异步递归并轮询队列直到其为空,将请求链接到队列的尾部(如果存在)是这样的:
async request(endpoint, domain, method, headers, query, body, attachments) {
const requestURL = `${(domain === "discord") ? this.discordBaseURL :
(domain === "trello") ? this.trelloBaseURL : domain}/${endpoint}`;
// get existing queue or create a new one
const queue = this.queueCollection.get(endpoint) || Promise.resolve();
// schedule request on the tail of the queue
const request = queue.then(
() => this.conditionalsHandler(endpoint, requestURL, method, headers, query, body, attachments)
);
// prevent errors from propagating along the queue
const tail = request.catch(() => {});
// enqueue the request
this.queueCollection.set(endpoint, tail);
try {
// propagates error handling to consumer
// waits for request to settle before executing finally block
return await request;
} finally {
// only remove promise from Map if this settled request is at the tail of the queue
if (this.queueCollection.get(endpoint) === tail) this.queueCollection.delete(endpoint);
}
}
这种方法允许request
到throw
而不会中断链,因此使用者可以处理错误,并且所有请求仍将按顺序发生,而不必依赖先前的请求是否成功,并且将始终清除不管queueCollection
是否抛出,都要在上一个未决请求上将request
向上移动。因此,await
并不是多余的。