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

时间:2014-08-08 20:00:30

标签: javascript jquery ajax

所以我有一个概念性的问题,关于根据返回的数据对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);

请求/结束索引(最小/最大),确定我将在数组中返回的数据量。 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循环中 - 我必须设置它实际工作的数量。试图将它存储在一个变量中似乎也没有效果......建议在这里?

1 个答案:

答案 0 :(得分:1)

这是一个基于您开始使用的代码的工作实现。代码被评论以帮助您了解正在发生的事情:

// 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/