Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/435.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用瓶颈对库中的API请求进行速率限制_Javascript_Typescript_Api_Asynchronous_Rate Limiting - Fatal编程技术网

Javascript 使用瓶颈对库中的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,…)一样访问它们 我创建了

我正在用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,…)
一样访问它们

我创建了一个名为
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))我已成功根据需要正确绑定上下文