如何将API请求的速率限制为每秒x?

时间:2019-06-05 12:15:45

标签: android rx-java2

我的应用重复发出API请求以下载数据块。不幸的是,服务器将API请求限制为每秒3个。 在下面的代码中,如何将请求的速率限制为每秒X个?

private void getHistoricalPrices(String currency, String start_date, String end_date, int granularity){
    // show download status
    currentDlPageIndex++;
    view.showDownloadingStatus(currentDlPageIndex, totalDlPages);

    // make the API call
    addDisposable(
            model.isNetworkAvailable()
                    .doOnSuccess(isNetworkAvailable -> {
                        if (!isNetworkAvailable) {
                            showErrorMessage();
                            Timber.v("no internet");
                        }
                    })
                    .filter(isNetworkAvailable -> true)
                    .flatMapSingle(isNetworkAvailable -> model.getHistoricalPrices(currency, start_date, end_date, String.valueOf(granularity)))
                    .subscribeOn(rxSchedulers.io())
                    .observeOn(rxSchedulers.mainThread())
                    .subscribe((Response<List<List<String>>> responseData) -> {
                        if (responseData != null && responseData.code() == HTTP_OK) {
                            List<List<String>> response = responseData.body();

                            if (response != null) {

                                // create list from downloaded data
                                ArrayList<HistoricPrice> tmpHistoricPriceList = new ArrayList<>(response.size());
                                for (List<String> rawHistoricPrice : response) {
                                    HistoricPrice historicPrice = new HistoricPrice(rawHistoricPrice.get(0), rawHistoricPrice.get(1), rawHistoricPrice.get(2), rawHistoricPrice.get(3), rawHistoricPrice.get(4), rawHistoricPrice.get(5));
                                    tmpHistoricPriceList.add(0, historicPrice);
                                }

                                // add the downloaded list to the main list being recreated
                                model.historicPriceList.addAll(tmpHistoricPriceList);
                                Timber.d("added %d records to memory", response.size());

                                // if there's more to download, download another chunk
                                if (intermediateDateSecs != null && intermediateDateSecs < endDateSecs){
                                    startDateSecs = tmpHistoricPriceList.get(tmpHistoricPriceList.size()-1).time + granularity;// add "granularity" to startDateSecs to avoid getting two exact data for the same time
                                    Date startDate = new Date(startDateSecs * 1000L);//requires milliseconds, not epoch
                                    String startStrDate = DateUtils.fromDateToString(startDate);

                                    intermediateDateSecs = startDateSecs + ((ApiService.MAX_HISTORIC_RETURN_VALUES - 1) * granularity);
                                    if (intermediateDateSecs > endDateSecs) intermediateDateSecs = endDateSecs;

                                    Date intermediateDate = new Date(intermediateDateSecs * 1000L);
                                    String intermediateStrDate = DateUtils.fromDateToString(intermediateDate);

                                    getHistoricalPrices(currency, startStrDate, intermediateStrDate, granularity);
                                } else {
                                    // no more to download, save data
                                    Timber.d("downloaded total of %d records", model.historicPriceList.size());
                                    view.hideDownloadingStatus();
                                    showSaveDataMessage();
                                }
                            }
                        }
                    }, error -> {
                        showErrorMessage();
                    })
    );
}

您会看到方法getHistoricalPrices()会自行调用以继续下载。此实现效果很好,除了服务器在每秒有太多API请求时抱怨。

1 个答案:

答案 0 :(得分:0)

您可以每隔X毫秒/秒执行一次请求,如下所示:

long interval = 0L; // Your desired interval here in milliseconds
Observable.interval(0, interval, TimeUnit.MILLISECONDS)
    .takeUntil(x -> isTaskComplete == true)
    // Other configuration calls go here
    .subscribe(); // make request here or in doOnNext()