如何在for循环中停止$ .ajax?

时间:2017-09-14 22:33:00

标签: javascript jquery ajax

我遇到了一个问题,我的api调用达到了超时限制,但是继续为所提供的其余请求循环,导致控制台中的n个超时日志数量(在这种情况下为5) 。我想要它,以便我可以按照break;的方式执行某些操作,然后完全退出,以便不记录其余的调用。例如。如果呼叫立即超时,则只记录一个超时日志而不是当前的5个,并且不会发出五个api请求。

let qs = {
    requests: 5,
    timeout: 1000
};
let prices = [];
let highest = 0;

const url = 'http://somedata.com';

function xhr(qs){
    return $.ajax({
        url: url,
        dataType: 'json',
        timeout: qs.timeout,
        success: function (data) {
            let json = JSON.stringify(data['price']);
            prices.push(json);
            getHighestPrice(prices);
            console.log(highest);
        },
        error: function(e, textstatus, message) {
            if(textstatus==="timeout") {
                console.error(textstatus);
            } else {
                console.error(textstatus);
            }
        }
    });
}

function makeRequest(qs) {
    for(let i = 0; i < qs.requests; i++) {
        xhr(qs);
    }
}

function getHighestPrice(arr) {
    for(let i = 0; i <= arr.length; i++) {
        if (arr[i] > highest) {
            highest = arr[i]
        }
    }

    return highest;
}

makeRequest(qs);

4 个答案:

答案 0 :(得分:1)

由于它是一个回调函数,它将以异步方式执行。因此,即使您从您提供的其中一个回调中抛出错误,其余的也将在稍后或更早执行。我能想到的解决方案之一就是有一个标志,如果其中一个AJAX导致错误,该标志将被设置为true。类似的东西:

var hasError = false;
$.ajax({
  error: function (e, textstatus, message) {
    if (textstatus === "timeout") {
      if (!hasError) console.error(textstatus);
      hasError = true;
    }
  }
});

答案 1 :(得分:1)

您的代码会立即发出所有请求

应该注意的是,此代码将停止&#34;链接&#34;一旦$.ajax出现任何错误,而不仅仅是超时 - 如果这不是必需的行为,那么还有一些事情要做

要仅在上一次成功时拨打电话,您可以链接$ .ajax返回的承诺

let qs = {
    requests: 5,
    timeout: 1000
};
let prices = [];
let highest = 0;
function xhr(qs){
    return $.ajax({
        url: url,
        dataType: 'json',
        timeout: qs.timeout,
        success: function (data) {
            let json = JSON.stringify(data['price']);
            prices.push(json);
            getHighestPrice(prices);
            console.log(highest);
        },
        error: function(e, textstatus, message) {
            if (textstatus==="timeout") {
                console.error(textstatus);
            } else {
                console.error(textstatus);
            }
        }
    });
}

function makeRequest(qs) {
    let p = $.when();
    for(let i = 0; i < qs.requests; i++) {
        p = p.then(() => xhr(qs));
    }
}
  

其他人已经指出您不需要将qs传递给xhr,但是,我假设您发布的代码可能会被简化,所以没有删除{ {1}}参数

另一种选择是

qs

答案 2 :(得分:0)

使用Promise.all()可以简化此用例。如果你不能使用promises尝试从错误处理程序中抛出异常。像这样:

$.ajax({
    error: function (e, textstatus, message) {
        if (textstatus === "timeout") throw e
    }
})

一定要抓住异常:

function makeRequest(qs) {
    try {
        for(let i = 0; i < qs.requests; i++) {
            xhr(qs);
        }
    } catch (e) { // Handle error here }
}

答案 3 :(得分:0)

要获得所需的行为,您必须按顺序拨打所有电话,即您不能开始下一个电话,直到上一个电话完成为止(否则您不会知道它是否已经失败)。

您可以使用done回调来确定是否应该进行下一次调用:

  function makeRequest(i) {
    xhr().done(function(){
      if (i < qs.requests){
        makeRequest(i+1)
      }
    })
  }

  makeRequest(0); // Kick things off here

此外,您不需要将qs变量传递到makeRequestxhr函数中。它不会在整个调用过程中发生变化,因此只需在xhr函数中使用它而不传递它。