Интервалы между вызовами API, чтобы избежать его переполнения - PullRequest
0 голосов
/ 11 ноября 2018

Я создаю торгового бота, которому иногда требуется совершать несколько вызовов API Exchange (например, обновлять N диаграмм после переподключения).Я хотел бы, чтобы эти вызовы были разнесены по времени, чтобы я не заканчивал тем, что заполнил API (я все еще не хочу отбрасывать все вызовы, которые мне нужно сделать, поэтому debounce / throttle - это не то, что я ищу),Как это:

Источник: [обновить диаграмму 1, обновить диаграмму 2, ..., обновить диаграмму N]

Наблюдаемо: [обновить диаграмму 1 -> ждать 1 секунду -> обновить диаграмму 2-> подождите 1 секунду -> ... -> обновить диаграмму N]

Я ожидаю, что эта наблюдаемая завершится за N - 1 секунду.

Как я могу построить такую ​​Наблюдаемую?(Я использую rxjs ^ 6.3.3)

Примечание: я изучал идею создания субъекта callAPI, оборачивающего все вызовы API и каким-то образом задерживающего их, но я тоже не могу понять это.

Спасибо .-

Обновление : Хорошо, в итоге я использовал Узкое место , например:

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

Тогда:chartsToReset.map(async (chart) => await limiter.schedule(() => exchangeAPI.updateChart(chart)))

Ответы [ 2 ]

0 голосов
/ 11 ноября 2018

Возможно, вы захотите взглянуть на interval функцию создания RxJS в сочетании с оператором mergeMap по этим направлениям

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 я добавил задержку, просто чтобы сделать ее немного более реалистичной.

Как правило, предметы требуются в относительно ограниченном числе случаев. Каждый раз, когда вы думаете, что вам нужно использовать тему, спросите себя, нет ли эквивалентного решения, которое требует простого использования операторов.

0 голосов
/ 11 ноября 2018

Вы можете использовать функцию, которая имеет 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
}

Обещающая документация по 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;
}
...