javascript - 如何限制返回输出的 typescript 函数

标签 javascript node.js typescript throttling delayed-execution

我正在使用 typescript 编写一个node.js应用程序。我的应用程序将有多个相互通信的服务。有些服务需要调用外部 API。此 API 对每秒可执行的调用数量有限制。因此,我想创建一项包装外部 API 调用的服务(我们称之为 ApiService)。其他服务将调用此服务,它将在队列中收集它们的请求并按顺序执行它们 - 每秒 N 个请求(为简单起见,我们假设每秒 1 个)。当服务 A 调用 ApiService 的方法时 - 它期望接收一个输出(接收 Promise 就可以了)。

现在我的问题是 - 如何在 ApiService 中对这些 API 调用进行排队,以便每隔 1 秒执行队列中的下一个调用,并将该 API 调用的输出返回给 ApiService 的调用者?

这是一个示例服务:

export class ServiceA {
   apiService: ApiService;

   public constructor(_apiService: ApiService) {
      apiService = _apiService;
   }

   public async DoWork() {
      // Do some stuff
      const output: number = await apiService.RetrieveA(param1, param2);
      // Do something with the output
   }
}

ApiService:

export class ApiService {
   queue: (() => Promise<any>)[] = [];

   public async RetrieveA(param1, param2): Promise<number> {
      const func = async () => {
         return this.CallApi(param1, param2);
      };

      this.queue.push(func);
      return func();
   }

   public async RunQueue() {
      while(true) {
         const func = this.queue.shift();
         if (!func) { continue; }
         // Call the function after 1 second
         await setTimeout(() => { func(); }, 1000);
      }
   }

   private async CallApi(param1, param2): Promise<number> {
      // Call the external API, process its output and return
   }
}

协调整个事情的主要方法:

var CronJob = require('cron').CronJob;

const apiService = new ApiService();
const service = new ServiceA(apiService);

new CronJob('* * * * * *', function() {
   service.DoWork();
}, null, true);

apiService.RunQueue();

我面临的问题是,当 RetrieveA 方法返回 func() 时 - 该函数被执行。我需要返回一个 Promise,但实际的函数执行需要在 RunQueue() 方法中发生。有办法实现这一点吗?我可以在不立即执行函数并等待此 promise 时返回 promise - 在 RunQueue 方法中调用函数时接收输出吗?

或者是否有不同的方法来解决限制返回输出的 API 调用的问题?

我是 Node.js/Typescript/JavaScript 世界的新手,因此感谢您的帮助:)

最佳答案

如果您想将对 RetreiveA 的调用限制为每秒 2 次,那么所有这些可能会简单得多:

//lib is here: https://github.com/amsterdamharu/lib/blob/master/src/index.js
import * as lib from '../../src/index'
const twoPerSecond = lib.throttlePeriod(2,1000);
export class ApiService {
  public RetrieveA(param1, param2): Promise<number> {
    //removed the resolver part, according to the typescript signature
    //  it should return a promise of number but resolver actually takes
    //  that number and returns void (undefined?)
    return twoPerSecond(this.CallApi.bind(this))([param1, param2]);
  }
  //change the signature of this function to take one parameter
  //  but deconsruct the array to param1 and param2
  private async CallApi([param1, param2]): Promise<number> {
    // Call the external API, process its output and return
  }
}

只有当该类只有一个实例时,您的方法才有效。如果您要创建多个实例并在这些实例上调用 RetrieveA,则不再限制对 callApi 的请求。

关于javascript - 如何限制返回输出的 typescript 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48099520/

相关文章:

javascript - 如何获取 before 方法附加的元素?

python - 使用 Eve 和 AngularJS 的 CORS 问题

javascript - webRTC-没有从其他同行获得流和冰候选人

javascript - AngularJS - 如何绑定(bind)到指令内的 ngRepeat 元素

javascript - 如何使用 jQuery 获取特定类的 ID?

Node.js 模块 - 添加链接依赖

javascript - 使用 Webpack 通过 JSON 文件配置 Angular

typescript - react-scripts 从 3.4 更新到 4.0 导致 Jest 版本错误

javascript - 我们可以将 .filter() 函数与搜索属性的条件规则一起使用吗?

javascript - 开头字符与正则表达式不匹配