Javascript 使用瓶颈对库中的API请求进行速率限制
我正在用TypeScript编写一个API包装器。我希望代码是异步的,以便最大限度地满足所讨论的API的速率限制。API希望以每秒1的最大速率提交请求 我打算实现一个API包装器,它被实例化一次,并允许使用对象到达不同的端点。例如,在更大的API中有一个Javascript 使用瓶颈对库中的API请求进行速率限制,javascript,typescript,api,asynchronous,rate-limiting,Javascript,Typescript,Api,Asynchronous,Rate Limiting,我正在用TypeScript编写一个API包装器。我希望代码是异步的,以便最大限度地满足所讨论的API的速率限制。API希望以每秒1的最大速率提交请求 我打算实现一个API包装器,它被实例化一次,并允许使用对象到达不同的端点。例如,在更大的API中有一个post和pool端点。我想像post\u object.post.submit\u request(argument1,…)或post\u object.pool.submit\u request(argument1,…)一样访问它们 我创建了
post
和pool
端点。我想像post\u object.post.submit\u request(argument1,…)
或post\u object.pool.submit\u request(argument1,…)
一样访问它们
我创建了一个名为state\u info
的对象,该对象在各个对象之间传递,其中包含一个用户代理头、登录信息(如果提供)和瓶颈库中的一个速率限制对象
我在测试时遇到的问题是,我的程序似乎没有限制请求的速率;无论我将瓶颈参数中的限制更改为什么,每次请求都会在大约.600秒内发生
我认为这与传递速率限制器对象有关,或者与从多个位置访问它有关,但我不确定
首先,这里是模型
对象的代码,它表示对API的访问
import axios, { AxiosRequestConfig } from "axios";
import { StateInfo, Method } from "./interfaces";
export class Model {
public stateInfo: StateInfo;
constructor(stateInfo: StateInfo) {
// Preserve rate limiter, user agent, etc.
this.stateInfo = stateInfo;
}
//Updated to funcName = () => {} syntax to bind "this" to this class context.
private submit_request = (query_url: string, method: Method) => {
if (this.stateInfo.username && this.stateInfo.api_key) {
const axiosConfig: AxiosRequestConfig = {
method: method,
url: query_url,
headers: { "User-Agent": this.stateInfo.userAgent },
auth: {
username: this.stateInfo.username,
password: this.stateInfo.api_key,
},
};
return axios(axiosConfig);
} else {
const axiosConfig: AxiosRequestConfig = {
method: "get",
url: query_url,
headers: { "User-Agent": this.stateInfo.userAgent },
};
return axios(axiosConfig);
}
};
public submit_throttled_request = (url: string, method: Method) => {
return this.stateInfo.rateLimiter.schedule(
this.submit_request,
url,
method
);
};
}
然后,我从中调用这个类的代码:
import { Model } from "./models/model";
import Bottleneck from "bottleneck";
const limiter: Bottleneck = new Bottleneck({ mintime: 1000, maxconcurrent: 1 });
const stateInfo = {
rateLimiter: limiter,
userAgent: "email@website.com | API Dev",
};
let modelObj: Model = new Model(stateInfo);
async function makeRequest() {
try {
let response = await modelObj.submit_throttled_request(
"https://www.website.com/api",
"get"
);
console.log(response.data.id + "|" + Date.now());
} catch (err) {
console.log(err);
}
}
let start = new Date();
for (let i = 0; i < 20; i++) {
makeRequest();
}
从“/models/Model”导入{Model};
从“瓶颈”导入瓶颈;
常数限制器:瓶颈=新瓶颈({mintime:1000,maxconcurrent:1});
常量stateInfo={
速率限制器:限制器,
用户代理:“email@website.com| API开发“,
};
让modelObj:Model=newmodel(stateInfo);
异步函数makeRequest(){
试一试{
let response=wait modelObj.submit\u throttled\u请求(
"https://www.website.com/api",
“得到”
);
log(response.data.id+“|”+Date.now());
}捕捉(错误){
控制台日志(err);
}
}
开始=新日期();
for(设i=0;i<20;i++){
makeRequest();
}
我的期望是,如果每秒只能提交一个请求,那么操作至少需要10秒。然而,我的平均值是一半,无论我在
mintime
中加入了什么,我都是在费尽周折之后才知道我自己问题的答案的
事实证明,在他们注意到的部分:
如果要将对象的方法作为作业传递,可能需要绑定()对象:
使用以下代码:
// instead of this:
limiter.schedule(object.doSomething);
// do this:
limiter.schedule(object.doSomething.bind(object));
// or, wrap it in an arrow function instead:
limiter.schedule(() => object.doSomething());
这就是我正在讨论的问题。我在未绑定作用域的情况下交付了axios(axioContext)
,因此没有向瓶颈速率限制器发送任何内容。包装如下:this.state_info.rateLimiter.schedule(()=>axios(axioContext))代码>我已成功根据需要正确绑定上下文