javascript - 基于数据对 API 进行后续 AJAX 调用的简洁方法

标签 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 循环中——我必须设置它实际工作的数字。尝试将其存储在变量中似乎效果不佳...此处有建议吗?

最佳答案

这是一个基于您开始使用的代码的有效实现。注释代码以帮助您了解正在发生的事情:

// 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 的工作 fiddle :

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

关于javascript - 基于数据对 API 进行后续 AJAX 调用的简洁方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25211366/

相关文章:

javascript - 需要 : HTML 5/Javascript UI Component to do "Matching"/"Data Mapping" UI

javascript/jquery - 识别从缓存加载

python - 如何从数据表发送选定的数据?

php - 启动时,每 10 秒运行一次 AJAX 请求

javascript - 如果访问被禁止,服务器端方法是否应该抛出异常?

ajax - 如何测试ajax页面

javascript - AngularJS 1.6 升级代码登录不再适用于 REST?

javascript - 使用 Chartist.js 如何更改圆环图笔划的颜色?

javascript - 在 iOS 上缓慢移动 html 元素位置

javascript - 检查是否输入了正确的电子邮件