干净的方式使后续AJAX调用基于数据的API

Clean way to make Subsequent AJAX Calls to API based on Data

本文关键字:于数据 API 数据 调用 方式使 AJAX      更新时间:2023-09-26

所以我有一个概念上的问题,关于基于返回的数据对API进行后续AJAX调用的最干净的方法。

一个简单的例子:

包含调用的函数应该是这样的:

function makeCall(headers, min, max) {
    $.ajax({ 
        headers: headers, 
        url: "https://coolapi.com/data?begIndex" + min + "&endIndex=" + max + "&begTimestamp=1404198000000&endTimestamp=1409554800000", 
        type: "GET", 
        dataType: 'JSON'
    });
}
makeCall(headers, 0, 20);

beg/end索引(min/max),决定我将在数组中返回的数据量。API将只返回数组中最多20个项目,但它也将返回一个COUNT,表示该数组中总共存在多少个项目。返回的数据示例如下:

{
    count = 133;
    result = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19];   
}

所以我的下一个调用是:

makeCall(headers, 20, 40);

等等,直到我从数组中得到所有133项。

问题是……在获得并存储数组中的所有133项之前,继续进行后续调用的最干净的方法是什么?考虑到计数可以是任意数,很难想象我如何做到这一点。我正在考虑在"成功"函数中嵌套更多的ajax调用,但如果我返回一个像300这样的数字,它就无法扩展。

有人对如何进行有什么建议吗?

提前感谢!

编辑:

因此,根据评论中的建议,我试图使调用递归-但它似乎没有按预期工作:

var theData = [];
var minCounter=0;
var maxCounter= minCounter + 20;
function makeCall(headers, min, max) {
$.ajax({ 
    headers: headers, 
    url: "https://coolapi.com/data?begIndex" + min + "&endIndex=" + max + "&begTimestamp=1404198000000&endTimestamp=1409554800000", 
    type: "GET", 
    dataType: 'JSON',
    success: function (data) {
        theData.push(data.result);
        newMin = minCounter + 20;
        if (data.count >= theData.length ) {
            makeCall(headers, newMin, maxCounter);
        }
    }
});
}
makeCall(headers, minCounter, maxCounter);

如何正确地增加变量以及设置标志?

第二个编辑:

下面的方法使用了第二个评论的建议,但是这里也有一些问题…

function doAjax(headers, min, dObject) {
    var max = min + 20;
    $.ajax({
        headers: headers, 
        url: "https://coolapi.com/data?begIndex" + min + "&endIndex=" + max + "&begTimestamp=1404198000000&endTimestamp=1409554800000", 
        type: "GET", 
        dataType: 'JSON',
        success: function (data) {
            results.push(data);
            window.count = data.count;
            dObject.resolve();
        }
    });
}
// array that will contain all deferred objects
var deferreds = [];
// array that will contain all results
var results = [];
// make the ajax calls
for (var i = 20; i < 133 ; i+= 20) {
    var dObject = new $.Deferred();
    deferreds.push(dObject);
    doAjax(headers, i, dObject);
}
// check if all ajax calls have finished
$.when.apply($, deferreds).done(function() {
    console.log(results);
});
var dObject = new $.Deferred();
doAjax(headers,0, dObject);

首先,数据没有按顺序压入数组。似乎没有办法解决这个问题。很奇怪的是,在for循环中,我必须设置数值才能让它工作。试图将其存储在变量中似乎并不奏效……建议吗?

下面是基于您开始使用的代码的工作实现。注释代码以帮助您理解正在发生的事情:

// Change these constants to suit your purposes.
var API_URL = 'https://coolapi.com/data';
var HEADERS = {};
var API_RESULTS_PER_REQUEST = 20;
var MAX_API_CALLS = 20;
// Count API calls to trigger MAX_API_CALLS safety lock.
var apiCalls = 0;
// Function we'll call to get all our data (see bottom).
function collectApiData(begTimestamp, endTimestamp) {
  var dataReady = jQuery.Deferred();
  var params = {
    'begTimestamp': begTimestamp,
    'endTimestamp': endTimestamp
  };
  var datasetsCollected = requestDatasets(params);
  jQuery.when(datasetsCollected).then(function(data) {
    dataReady.resolve(data);
  });
  return dataReady;
}
// Makes individual AJAX call to API
function callApi(params, headers) {
  var $request = jQuery.ajax({
    url: API_URL,
    headers: headers,
    data: params,
    type: 'GET',
    dataType: 'JSON'
  });
  return $request;
}
// Recursive function that makes API calls until data is collected, there is an
// error, or MAX_API_CALLS limit is hit.
function requestDatasets(params, resultsReady, resultsFetched) {
  resultsReady = ( resultsReady !== undefined ) ? resultsReady : jQuery.Deferred();
  resultsFetched = ( resultsFetched !== undefined ) ? resultsFetched : [];
  // Trigger safety to avoid API abuse
  if ( apiCalls >= MAX_API_CALLS ) {
    console.error('Exceeded max API calls:', MAX_API_CALLS);
    resultsReady.resolve(resultsFetched);
  }
  // Set index data
  params.begIndex = resultsFetched.length;
  params.endIndex = resultsFetched.length + API_RESULTS_PER_REQUEST;
  // Request dataset from API
  var apiRequest = callApi(params, HEADERS);
  apiCalls += 1;
  // Callback once API request has completed and data is ready
  jQuery.when(apiRequest).done(function(data) {
    var apiResultCount = data.count;
    resultsFetched = resultsFetched.concat(data.result);
    console.debug('Fetched', resultsFetched.length, 'of', apiResultCount, 'API results');
    if ( apiResultCount > resultsFetched.length ) {
      console.debug('Making another API call');
      requestDatasets(params, resultsReady, resultsFetched);
    }
    else {
      console.debug('Results all fetched!');
      resultsReady.resolve(resultsFetched);
    }
  });
  jQuery.when(apiRequest).fail(function(data) {
    console.error('API error: returning current results.');
    resultsReady.resolve(resultsFetched);
  });
  return resultsReady;
}
// Run script
var dataReady = collectApiData('1404198000000', '1409554800000');
jQuery.when(dataReady).then(function(data) {
  console.log(data);
});

这是一个使用httpbin.org模拟API的工作小提琴:

http://jsfiddle.net/klenwell/mfhLxun2/