RxJS服务呼叫转移/排队

RxJS服务呼叫转移/排队,rxjs,Rxjs,我正在尝试使用RxJS实现服务调用节流/排队 例如,谷歌地图的地理编码API。假设我不希望每秒调用一次以上,但我的应用程序的一个或多个部分可能会更频繁地请求地理代码。我希望请求排队,相邻请求之间至少相隔1s,但如果在等待期间不再需要请求,我还希望能够“取消”请求 这是RxJS的一种适用用法吗?如果是,这会是什么样子 谢谢。这里有一些东西可以指导你(): //辅助函数 函数从_队列中删除_(队列,id){ forEach(函数(x,索引){ if(x.execute.request==id){ 队

我正在尝试使用RxJS实现服务调用节流/排队

例如,谷歌地图的地理编码API。假设我不希望每秒调用一次以上,但我的应用程序的一个或多个部分可能会更频繁地请求地理代码。我希望请求排队,相邻请求之间至少相隔1s,但如果在等待期间不再需要请求,我还希望能够“取消”请求

这是RxJS的一种适用用法吗?如果是,这会是什么样子


谢谢。

这里有一些东西可以指导你():

//辅助函数
函数从_队列中删除_(队列,id){
forEach(函数(x,索引){
if(x.execute.request==id){
队列拼接(索引,1);
}
});
//log('删除后的队列',队列);
}
函数添加到队列(队列,id){
push({execute:{request:id}});
}
函数getFirstInQueue(队列){
返回队列[0];
}
函数noop(x){}
功能日志(标签){
返回函数(x){
console.log.call(console,label,x);
}
}
函数时间戳(标签){
返回函数(x){
console.log.call(console,Date.now()-startingDate,label,x);
}
}
功能标签(标签){
返回函数(x){
var res={};
res[label]=x;
返回res;
}
}
var startingDate=Date.now();
var请求$=Rx.Observable.generateWithRelativeTime(
{请求:1},
函数(x){返回x.request<10;},
函数(x){return{request:x.request+1};},
函数(x){return x;},
函数(x){return 100;}
);
var CanceledRequests$=Rx.Observable.generateWithRelativeTime(
{请求:1},
函数(x){返回x.request<20;},
函数(x){return{request:x.request+4};},
函数(x){return x;},
函数(x){return 500;}
);
var timer$=Rx.Observable.interval(990).map(函数(){return{}).take(10);
var source$=Rx.Observable.merge(
请求$.map(标签('execute'),
cancelledRequests$.map(标签('cancel')),
计时器$
)
//.do(日志(“源”);
controlledSource$=源$
.scan(功能(状态、命令){
var requestsToExecuteQueue=state.requestsToExecuteQueue;
if(命令.取消){
从_队列中删除_(requestsToExecuteQueue,command.cancel.request);
}
if(command.execute){
将_添加到_队列(requestsToExecuteQueue,command.execute.request);
}
console.log('queue',requestsToExecuteQueue.slice())
返回{
命令:命令,,
requestExec$:Rx.可观察
.return(getFirstInQueue(requestsToExecuteQueue))
.filter(函数(x){return x})
.do(函数(x){remove_from_queue(requestsToExecuteQueue,x.execute.request)}),
requestsToExecuteQueue:requestsToExecuteQueue
}
},{command:undefined,requestExec$:undefined,requestsToExecuteQueue:[]})
.pluck('requestExec$')
.样本(可观测接收间隔(1000))
.mergeAll();
controlledSource$.do(时间戳('executing request:')).subscribe(noop)
基本上:

  • scan
    用于管理状态(请求队列、添加和删除)
  • 对于每个请求,我们传递一个observable,它(在订阅时)释放队列的第一个元素,并从队列中删除该元素
  • sample
    用于每秒获得一个这样的可观测值
  • mergeAll
    允许订阅该可观察的
  • 我们必须使用
    timer$
    对象来继续轮询队列,即使请求源已完成(您仍然需要清空剩余请求的队列)。例如,您可以在源代码完成后让timer$发出X秒,或者任何最适合您的方式,使该逻辑适应您的实际情况

是的,这是Rxjs的一种适用用法。您应该能够找到一种使用Rxjs操作符的方法,例如
scan
sample
,可能还有
bufferWithTime
。当你有一个工作代码,不要犹豫,把它张贴在这里。其他同样关心的人也会感激的。如果您无法获得工作代码,请发回您的问题。感谢您的指点,我将查看我可以组合的内容,并在此处共享。这也是一本非常好的读物:。
受控的
操作符允许您管理请求队列,并在需要的时间提取请求。
// Helper functions
function remove_from_queue(queue, id) {
  queue.forEach(function(x, index){
    if (x.execute.request === id) {
      queue.splice(index, 1);
    }
  });
//  console.log('queue after removal', queue);
}

function add_to_queue (queue, id){
  queue.push({execute : {request : id}});
}

function getFirstInQueue(queue){
  return queue[0];
}

function noop(x) {}

function log(label) {
  return function (x) {
    console.log.call(console, label, x);
  }
}

function timestamp(label){
  return function (x) {
    console.log.call(console, Date.now() - startingDate, label,x );
  }
}

function label(label){
  return function (x) {
    var res = {};
    res[label] = x;
    return res;
  }
}

var startingDate = Date.now();

var requests$ = Rx.Observable.generateWithRelativeTime(
  {request : 1},
  function (x) { return x.request < 10; },
  function (x) { return {request : x.request + 1}; },
  function (x) { return x; },
  function (x) { return 100 ; }
);

var cancelledRequests$ = Rx.Observable.generateWithRelativeTime(
  {request : 1},
  function (x) { return x.request < 20; },
  function (x) { return {request : x.request + 4}; },
  function (x) { return x; },
  function (x) { return 500 ; }
);

var timer$ = Rx.Observable.interval(990).map(function (){return {}}).take(10);

var source$ = Rx.Observable.merge(
  requests$.map(label('execute')),
  cancelledRequests$.map(label('cancel')),
  timer$
)
//.do(log('source'));

controlledSource$ = source$
  .scan(function (state, command){
    var requestsToExecuteQueue = state.requestsToExecuteQueue;
    if (command.cancel) {
      remove_from_queue(requestsToExecuteQueue, command.cancel.request);
    }
    if (command.execute) {
      add_to_queue(requestsToExecuteQueue, command.execute.request);
    }
    console.log('queue', requestsToExecuteQueue.slice())

    return {
      command : command,
      requestExec$ : Rx.Observable
        .return(getFirstInQueue(requestsToExecuteQueue))
        .filter(function(x){return x})
        .do(function(x){remove_from_queue(requestsToExecuteQueue, x.execute.request)}),
      requestsToExecuteQueue : requestsToExecuteQueue
    }
  }, {command : undefined, requestExec$ : undefined, requestsToExecuteQueue : []})
  .pluck('requestExec$')
  .sample(Rx.Observable.interval(1000))
  .mergeAll();

controlledSource$.do(timestamp('executing request:')).subscribe(noop)