node.js - 我在 node.js 中使用的递归方法是否有替代方法?
问题描述
我在 requestHandler 中实现了一个递归函数,用于序列化 API 请求并确保当前没有请求端点。为了确保当前没有请求端点,我将它添加到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;
}
}
解决方案
是的,您可以通过使用queueCollection
aMap<string, Promise>
而不是 a来删除递归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
这个原因,这里不是多余的。
推荐阅读
- html - 表属性与引导程序不正确
- java - Java 8 替代 Map.entry() 用于将值映射到新 Map?
- firebase - Firestore Cloud Functions,Multiple Functions 和 One Big Functions 哪个更好?
- c# - 在基本视图模型中定义命令
- web2py - web2py sqlform.grid 搜索
- excel - VBA:使单元格超出范围
- html - 如何使按钮内的链接在悬停时更改颜色而不悬停在链接上
- javascript - 在没有根 vue js 文件的情况下将插件添加到 vu 实例作为“Vue.use()”
- tensorflow - 在 tf.print 中动态更改 output_stream 的值/文件?
- amazon-web-services - AWS RDS 每天重置我的 RDS 密码问题