rxjs速率限制(每秒请求数)和并发性

rxjs速率限制(每秒请求数)和并发性,rxjs,Rxjs,我正试图找出如何在rxjs中编写一个速率限制器。用于访问大多数API(twitter、facebook等),如果开箱即用的方法不支持,我假设可以编写一个调度器。例如,highland.js就有。我不想放弃任何项目,如窗口,样品等 var source = Rx.Observable.create(function (observer) { // queue of requests _.each(requests, function(r) { observer.onNext(r)

我正试图找出如何在rxjs中编写一个速率限制器。用于访问大多数API(twitter、facebook等),如果开箱即用的方法不支持,我假设可以编写一个调度器。例如,highland.js就有。我不想放弃任何项目,如窗口,样品等

var source = Rx.Observable.create(function (observer) {

  // queue of requests
  _.each(requests, function(r) {
    observer.onNext(r);
  });

  observer.onCompleted();

  // Any cleanup logic might go here
  return function () {
    console.log('disposed');
  }
})
  // what goes here, if built in (e.g. 2 requests per 2 seconds or 15 request per 15 minutes)

// SHOULD ONLY RUN
var subscription = source.subscribe(
  function (x) { console.log('onNext: %s', x); },
  function (e) { console.log('onError: %s', e); },
  function () { console.log('onCompleted'); });
编辑1: 考虑一下这样的事情,使用令牌桶算法,仍然很粗糙,但是

Rx.Observable.prototype.tokenBucket=函数(选项,调度器){
功能时间(){
返回新日期().getTime();
}
变量桶={
容量:选项。容量| |无穷大,
左:选项。容量,
最后:time(),
TokensPrinterval:options.TokensPrinterval,
间隔:options.interval
};
//var BUCKET=\合并(defaultOptions,options);
控制台日志(桶);
var source=这个,
scheduler=scheduler | |(scheduler=Rx.scheduler.timeout);
返回Rx.Observable.create(函数(观察者){
var d1=源.subscribe(函数(mainValue){
返回油门(主值);
});
功能节流阀(x,令牌){
if(BUCKET.capacity==无穷大){
返回观测器onNext(x);
}//返回x;
//每S毫秒要添加的令牌数=(r*S)/1000。
var self=铲斗;
var now=time();
var deltaMS=Math.max(现在-self.last,0);
self.last=现在;
var dripAmount=deltaMS*(self.tokensPerInterval/self.interval);
self.left=Math.min(self.left+dripAmount,self.capacity);
如果(自左<1){
var区间=数学区间((1-自左)*自区间);
scheduleWithRelative(间隔,函数(s,i){
回油节流阀(x);
});
}否则{
self.left-=令牌| | 1;
console.log('calling');
返回观测器onNext(x);
}
}
返回函数(){
d1.处置();
log('disposed tokenBucket');
};
});
};
var start=力矩();
var源=接收可观测范围(1,20)
.tokenBucket({容量:2,tokensPerInterval:2,间隔:2000})
var subscription=source.subscripte(
函数(x){console.log('onNext:%s',x);addToDom(x);},
函数(e){console.log('onError:%s',e);},
函数(){console.log('onCompleted');});
函数addToDom(x){
var ul=document.getElementById('c');
var li=document.createElement('li');
li.innerHTML=x+'-'+moment().diff(开始,'seconds')+'s ago';
ul.儿童(li);
}


    如果您只想删除其间发生的事件,可以使用windowWithTimeOrCount+throttleFirst:

    var subscription = source
    
     //Splits the events into 15 minute windows
     .windowWithTimeOrCount(900000 /*15 minutes*/, 15) 
    
     //Stops us from receiving more than one window in 15 minutes
     .throttleFirst(900000 /*15 minutes*/)
    
     //Flatten the observable
     .concatAll()
     .subscribe(
      function (x) { console.log('onNext: %s', x); },
      function (e) { console.log('onError: %s', e); },
      function () { console.log('onCompleted'); });
    
    工作示例(控制台中的输出):

    var source=Rx.Observable.generateWithRelativeTime(
    0,
    函数(x){返回x<1000;},
    函数(x){返回x+1;},
    函数(x){return x;},
    函数(x){返回Math.floor(Math.random()*100);});
    来源
    .windowWithTimeOrCount(1000,3)
    .节流阀第一(1000)
    .concatAll()
    .subscribe(console.log.bind(console))
    
    如果您只想删除其间发生的事件,可以使用windowWithTimeOrCount+throttleFirst:

    var subscription = source
    
     //Splits the events into 15 minute windows
     .windowWithTimeOrCount(900000 /*15 minutes*/, 15) 
    
     //Stops us from receiving more than one window in 15 minutes
     .throttleFirst(900000 /*15 minutes*/)
    
     //Flatten the observable
     .concatAll()
     .subscribe(
      function (x) { console.log('onNext: %s', x); },
      function (e) { console.log('onError: %s', e); },
      function () { console.log('onCompleted'); });
    
    工作示例(控制台中的输出):

    var source=Rx.Observable.generateWithRelativeTime(
    0,
    函数(x){返回x<1000;},
    函数(x){返回x+1;},
    函数(x){return x;},
    函数(x){返回Math.floor(Math.random()*100);});
    来源
    .windowWithTimeOrCount(1000,3)
    .节流阀第一(1000)
    .concatAll()
    .subscribe(console.log.bind(console))
    
    如果您不想丢失任何通知,可以使用缓冲区或它的一种变体(使用time/count/time或count)。 它基本上将通知组合在一个数组中,并在以下情况下转发该数组:

    • 可观察的通知
    • 计时器过期
    • 已达到通知数
    • 以上各项的结合
    因此,您可以将通知缓冲在一个数组中,每分钟只接收一次,或者在100个通知到达时接收一次


    如果您不想丢失任何通知,可以使用缓冲区或它的一种变体(带有time/count/time或count)。 它基本上将通知组合在一个数组中,并在以下情况下转发该数组:

    • 可观察的通知
    • 计时器过期
    • 已达到通知数
    • 以上各项的结合
    因此,您可以将通知缓冲在一个数组中,每分钟只接收一次,或者在100个通知到达时接收一次


    我在我的个人项目中遇到了一个非常类似的问题,并决定将一个可重用的解决方案作为npm包发布


    与此不同的是,它不会强制延迟每个事件。

    我在我的个人项目中遇到了一个非常类似的问题,并决定将一个可重用的解决方案作为npm包发布


    与之不同的是,它不会对每个事件强制延迟。

    我现在只看
    generateWithRelativeTime
    。我不想在处理队列中丢弃任何内容。真的只是想防止超过特定api的速率限制。如果您不想删除任何元素,还可以查看
    controlled
    。@dre,如果您不想删除任何事件,您想如何处理额外的事件?等下一次开门?取决于可能开始堆叠的下一个应用程序。或者您只是在某个时间间隔ping端点?是的,基本上是一个处理队列,所以您不想删除任何内容,但必须遵守速率限制。@dre请参阅我的备选方案。我想它可能更接近你想要的。我现在只看
    generateWithRelativeTime
    。我不想在处理队列中丢弃任何内容。真的只是想防止超过