使用Ajax方法的相同实例多次调用后返回Promise

时间:2019-07-17 14:59:18

标签: javascript ajax promise

我正在将Ajax与JQuery一起使用,以从一次仅返回100条记录的API提取数据。如果我的查询给出的结果包含100条以上的记录,则API将在响应中包含“ offset”参数。我必须在新的API调用中使用此offset参数来获取接下来的100条记录。如果还有更多记录要提取,则该API将包含一个新的offset参数。依此类推,直到提取所有记录。

如您所见,我已经解决了此问题,方法是调用函数本身直到不再包含“ offset”参数。即直到没有更多记录可以提取。

由于API的这种行为,我不能使用Ajax方法自己的.done函数,因为它将被执行多次(对于Ajax方法的每次迭代)。

在完成所有Ajax调用后,如何调整下面的功能以返回承诺?

function getContracts(offset) {

    var data = {};

    if (offset !== undefined) {
      data["offset"] = offset;
    }

    $.ajax({
      url: url,
      headers: {
        Authorization: apiKey
      },
      data: data,
      success: function(result){

        $.each(result.records, function() {        
            contracts.push(this);
        });

        if (result.hasOwnProperty("offset")) {
          getContracts(result.offset);
        }

      }

    });

  }

实际和完整的代码:

  var objectContracts = [];
  var landContracts = [];
  var locations = [];
  var customers = [];
  var landOwners = [];
  var frameworkAgreements = [];

  function getObjectContracts(offset) {

    return new Promise((resolve, reject) => {

      var data = {};

      data["view"] = 'Alla Objektsavtal';

      if (offset !== undefined) {
        data["offset"] = offset;
      }

      $.ajax({
        url: url + "Objektsavtal",
        headers: {
          Authorization: apiKey
        },
        data: data,
        success: function(result){

          $.each(result.records, function() {        
              objectContracts.push(this);
          });

          if (result.hasOwnProperty("offset")) {
            getObjectContracts(result.offset);
          } else {
            resolve();
          }

        }
      });

    });

  }

  function getLandContracts(offset) {

    return new Promise((resolve, reject) => {

      var data = {};

      data["view"] = 'Alla Markavtal';

      if (offset !== undefined) {
        data["offset"] = offset;
      }

      $.ajax({
        url: url + "Markavtal",
        headers: {
          Authorization: apiKey
        },
        data: data,
        success: function(result){

          $.each(result.records, function() {        
              landContracts.push(this);
          });

          if (result.hasOwnProperty("offset")) {
            getLandContracts(result.offset);
          } else {
            resolve();
          }

        }

      });

    });

  }

  function getLocations(offset) {

    return new Promise((resolve, reject) => {

      var data = {};

      data["view"] = 'Alla Uppställningsplatser';

      if (offset !== undefined) {
        data["offset"] = offset;
      }

      $.ajax({
        url: url + "Uppställningsplatser",
        headers: {
          Authorization: apiKey
        },
        data: data,
        success: function(result){

          $.each(result.records, function() {        
              locations.push(this);
          });

          if (result.hasOwnProperty("offset")) {
            getLocations(result.offset);
          } else {
            resolve();
          }

        }

      });

    });

  }

  function getCustomers(offset) {

    return new Promise((resolve, reject) => {

      var data = {};

      data["view"] = 'Alla Kunder';

      if (offset !== undefined) {
        data["offset"] = offset;
      }

      $.ajax({
        url: url + "Kunder",
        headers: {
          Authorization: apiKey
        },
        data: data,
        success: function(result){

          $.each(result.records, function() {        
              customers.push(this);
          });

          if (result.hasOwnProperty("offset")) {
            getCustomers(result.offset);
          } else {
            resolve();
          }

        }

      });

    });

  }

  function getLandOwners(offset) {

    return new Promise((resolve, reject) => {

      var data = {};

      data["view"] = 'Alla Markägare';

      if (offset !== undefined) {
        data["offset"] = offset;
      }

      $.ajax({
        url: url + "Markägare",
        headers: {
          Authorization: apiKey
        },
        data: data,
        success: function(result){

          $.each(result.records, function() {        
              landOwners.push(this);
          });

          if (result.hasOwnProperty("offset")) {
            getLandOwners(result.offset);
          } else {
            resolve();
          }

        }

      });

    });

  }

  function getFrameworkAgreements(offset) {

    return new Promise((resolve, reject) => {

      var data = {};

      data["view"] = 'Alla Ramavtal';

      if (offset !== undefined) {
        data["offset"] = offset;
      }

      $.ajax({
        url: url + "Ramavtal",
        headers: {
          Authorization: apiKey
        },
        data: data,
        success: function(result){

          $.each(result.records, function() {        
              frameworkAgreements.push(this);
          });

          if (result.hasOwnProperty("offset")) {
            getFrameworkAgreements(result.offset);
          } else {
            resolve();
          }

        }

      });

    });

  }

1 个答案:

答案 0 :(得分:2)

如果我完全理解您的问题,那么您想解决一个Promise的问题,如果您的Ajax请求的响应中没有offset

我尚未测试此代码,但是您可以执行以下操作:

function getContracts(offset) {
  return new Promise((resolve, reject) => {
    var data = {};

    if (offset !== undefined) {
      data['offset'] = offset;
    }

    $.ajax({
      url: url,
      headers: {
        Authorization: apiKey,
      },
      data: data,
      success: function(result) {
        $.each(result.records, function() {
          contracts.push(this);
        });

        if (result.hasOwnProperty('offset')) {
          getContracts(result.offset);
        } else {
          // I guess this is what you want
          // If there is no offset property => resolve the promise
          resolve('Your result goes here');
        }
      },
    });
  });
}

请参见else块。
您可以在result内部传递最终的resolve(无论您希望完成的任务是什么)。例如,您可以创建一个数组并将结果附加到该数组,最后可以在resolve内传递该数组。

您可以使用.then()async/await

解决此问题
async () => {
  const result = await getContracts(offset);
};

getContracts(offset).then(result => { console.log(result) });

如果看到一些未处理的承诺拒绝警告/错误,则可以始终将try/catch块与async / await一起使用,然后将.catch与.then之后一起使用。

编辑:

  • 首先,您没有在resolve内部传递任何内容。无论您在解决方案中传递的内容如何,​​都将反映在.then(result)中。
  • 第二,您拥有全局变量并将所有数据存储在其中。因此,现在您不需要将它们传递到resolve中,但这不是一个好方法,因为外部的任何函数或代码都可以对其进行修改。因此,我举一个例子。
function getObjectContracts(offset) {
  return new Promise((resolve, reject) => {
    var data = {};

    const objectContracts = [];

    data['view'] = 'Alla Objektsavtal';

    if (offset !== undefined) {
      data['offset'] = offset;
    }

    $.ajax({
      url: url + 'Objektsavtal',
      headers: {
        Authorization: apiKey,
      },
      data: data,
      success: function(result) {
        $.each(result.records, function() {
          objectContracts.push(this);
        });

        if (result.hasOwnProperty('offset')) {
          getObjectContracts(result.offset);
        } else {
          resolve(objectContracts);
        }
      },
    });
  });
}

现在,另一个问题是,如何立即兑现所有这些承诺。

const finalFunction = async () => {
  const [result1, result2, result3] = await Promise.all([
    getObjectContracts(offset1),
    getLandContracts(offset2),
    getLocations(offset3),
  ]);

  console.log(result1, result2, result3);
};

finalFunction();