间隔调用API以避免泛滥

时间:2018-11-11 01:58:13

标签: javascript rxjs6

我正在构建一个交易机器人,有时需要多次调用Exchange的API(例如,重新连接后刷新N个图表)。我想让这些调用有时间间隔,这样我就不会淹没API(我仍然不想放弃我需要进行的任何调用,因此去抖动/节流不是我想要的) 。像这样:

来源:[更新图表1,更新图表2,...,更新图表N]

可观察到:[更新图表1->等待1秒->更新图表2->等待1秒-> ...->更新图表N]

我希望这个观察结果能在N-1秒内完成。

如何构建这样的Observable? (我正在使用rxjs ^ 6.3.3)

注意:我正在研究使用callAPI Subject将所有对API的调用包装起来并以某种方式延迟它们的想法,但是我也无法弄清楚。

谢谢。-

更新:好的,我最终使用了Bottleneck,就像这样:

const limiter = new Bottleneck({
  minTime: 1000
})

然后:chartsToReset.map(async (chart) => await limiter.schedule(() => exchangeAPI.updateChart(chart)))

2 个答案:

答案 0 :(得分:0)

您可以使用具有Promise + setTimeout和递归函数的函数(类似):

var runQueries = function(source) {
  if (source.length > 0) {
    runQuery(source[0]).then(() => runQueries(source.slice(1));
  } else {
    console.log('done!')
  }
}
// this is just pseudo code...
var runQuery = function(item) {
  //var promise = new Promise
  //run code
  // setTimeout for 1000 to resolve promise
  // return promise
}

Promise documentation on MDN

修改

如果迭代函数对数组无损,并且您可以使用属性queryRunning和查询(或其他方法)(我没有使用rxjs,因此您必须对该格式稍作修改) ):

var next = function(query) {
  // queries and queryRunning are properties on the thing doing these calls
  queries.push(query);
  if (!queryRunning) {
    runQueries();
  }
}
var runQueries = function() {
  if (queries.length > 0) {
    queryRunning = true;
    runQuery(queries.shift()).then(() => runQueries();
  } else {
    queryRunning = false;
    console.log('done!')
  }
}
// this is just pseudo code...
var runQuery = function(query) {
  var promise1 = new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('complete');
    }, 1000);
  });
  //run code to handle query
  return promise1;
}

答案 1 :(得分:0)

您可能希望沿着这些思路结合interval运算符来查看mergeMap RxJS创建函数

const updates = ['chart1', 'chart2', 'chart3'];

// this function simulates fetching of data for the chart
function getUpdatedChartData(chartName: string) {
  return of({chart: chartName, data: [chartName + ' 1', chartName + ' 2', chartName + ' 3']}).pipe(
    delay(Math.random() * 2000)
  )
}

const theObservableIWantToBuild = interval(1000).pipe(
  take(updates.length),
  mergeMap(i => getUpdatedChartData(updates[i]).pipe(
    tap(chartData => {
      console.log(JSON.stringify(chartData, null, 3)) 
      // do something with chart data)
    }),
    map(() => updates[i])
  )),
)

您可能会看到,在模拟函数getUpdatedChartData中,我添加了一个延迟,只是为了使其更加真实。

作为一般规则,在相对有限的情况下,需要受试者。每当您认为需要使用Subject时,请问自己是否存在不存在需要简单使用运算符的等效解决方案。