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

Javascript 如何在for循环中停止$.ajax?,javascript,jquery,ajax,Javascript,Jquery,Ajax,我遇到了一个问题,我的api调用达到了它的超时限制,但继续循环提供的其余请求,导致控制台中出现n个超时日志(在本例中为5个)。我想要它,这样我就可以沿着中断的路线做一些事情然后完全退出,这样剩余的调用就不会被记录。例如,如果调用立即超时,将只记录一个超时日志,而不是当前的5个,并且五个api请求都不会发出 let qs = { requests: 5, timeout: 1000 }; let prices = []; let highest = 0; const url =

我遇到了一个问题,我的api调用达到了它的超时限制,但继续循环提供的其余请求,导致控制台中出现
n
个超时日志(在本例中为5个)。我想要它,这样我就可以沿着
中断的路线做一些事情
然后完全退出,这样剩余的调用就不会被记录。例如,如果调用立即超时,将只记录一个超时日志,而不是当前的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);
让qs={
请求:5,
超时:1000
};
让价格=[];
设最高值=0;
常量url=http://somedata.com';
函数xhr(qs){
返回$.ajax({
url:url,
数据类型:“json”,
超时:qs.timeout,
成功:功能(数据){
让json=json.stringify(数据['price']);
prices.push(json);
获得最高价格;
console.log(最高);
},
错误:函数(e、文本状态、消息){
如果(textstatus==“超时”){
控制台错误(文本状态);
}否则{
控制台错误(文本状态);
}
}
});
}
函数makeRequest(qs){
for(设i=0;i
使用Promise.all()可以简化此用例。如果无法使用承诺,请尝试从错误处理程序引发异常。像这样:

$.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 }
}
函数生成请求(qs){
试一试{
for(设i=0;i
要获得所需的行为,您必须按顺序进行所有调用,即在前一个调用完成之前,您不能启动下一个调用(否则您将不知道它是否失败)

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

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

  makeRequest(0); // Kick things off here
函数makeRequest(i){
xhr().done(函数()){
如果(i

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

因为它是一个回调,所以它将异步执行。因此,即使您从提供的回调中抛出一个错误,其余的都将稍后或更早执行。我可以想到的一个解决方案是,如果某个AJAX导致错误,将设置一个标志为true。比如:

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

您的代码一次发出所有请求

应该注意的是,一旦
$中出现任何错误,此代码将停止“链接”。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));
    }
}


break
不会有任何帮助,因为所有请求都会立即启动-您可能需要查看在我尝试时部分有效的中止。它会中止当前请求,但不会中止后续请求。。。这是什么意思?您的代码不尝试中止任何内容您是否理解,使用您的代码时,所有五个请求都将始终启动?这是个问题吗?您是否只想在请求1成功时发出请求2,如果请求2成功时发出请求3等等,或者您想发出5个请求,但只记录第一个超时?目前有两个答案可以做到这一点谢谢您的回复!我刚刚实现了它,但它仍然记录了5个错误。这根本没有解决这个问题。我想这是因为这是一个竞争条件。如果我在
xhr(qs)
上面的循环中注销
I
,1,2,3,4,5在Catch出现错误之前全部注销,您可以发布一个示例jsbin吗?Throw肯定会停止循环。不,它不会@rapta,因为所有请求都是在任何请求有机会超时之前启动的-循环在第一个请求有机会超时之前完成,在通过时调用goodqs@tim很高兴能贡献这一小部分,如果没有别的。这是否没有提供所需的行为?也许我需要做更多的工作,但是当我实现这一点时,我得到了一个
success不是xhr()的函数。
。correct,success不是$.ajax返回的对象的函数。。。也许应该
。完成
。然后
instead@JaromandaX对的应该
完成
。愚蠢的错误对不起,谢谢你纠正我。这只是使它不会记录多次。不幸的是,电话和日志仍在进行中。Jaromanda X对此解释得最好。如果第一个请求成功,而第二个请求没有成功,那么剩下的三个电话就不会打了。我还以为你是这么问的呢。“例如,如果呼叫立即超时,将只记录一个超时日志,而不是当前的5个。”请更具体、更清楚地回答您的问题。谢谢!我不知道
$。当
$。当()
像(但不是完全像)
Promise.resolve()
-jQuery有它自己的承诺“愿景”,从Promise/a+specCool中删除一点,我会研究一下,我不知道jQuery有自己的承诺。
let qs = {
    requests: 5,
    timeout: 1000
};
let prices = [];
let highest = 0;
function xhr(qs){
    return $.ajax({
        url: url,
        dataType: 'json',
        timeout: qs.timeout
    }).then(data => {
        let json = JSON.stringify(data['price']);
        prices.push(json);
        getHighestPrice(prices);
        console.log(highest);
    });
}

function makeRequest(qs) {
    let p = $.when([]);
    for(let i = 0; i < qs.requests; i++) {
        p = p.then(() => xhr(qs));
        // or p.then(xhr); if you don't need to pass qs on to xhr function (remove qs argument in xhr as well)
    }
    p.then(() => {
        // this is run once all have completed
    }).fail(reason => {
        // this is run if there's a failure anywhere
    });
}