1

我正在尝试遍历 .ball 类的元素并检查其关联的 url 是否存在:

$(".ball").each(function(i){

    var url;

    var c_day = $(this).data('day');
    var c_mon = $(this).data('mon');
    var c_year = $(this).data('year');

    url = c_year + "/" + c_mon + "/" + c_day + ".html";

    $.ajax({

        url: url, 
        error: function()
        {
              alert('file: ' + url + '   does not exist');
        },
        success: function()
        {
            alert('file: ' + url + 'EXXXXXXISTS!!!!!');
            blogA[ blog_count ] = url;
            blog_count++;
            $(this).css("color", "red" );           
        }
    });
 });

我做了一些研究并读到在 .each 中使用 .ajax 会导致很多问题,但我无法解决如何解决它。

问题是我得到了非常奇怪的结果(与异步有关?)。如果我在 ajax 之外提醒 url,它会正确地遍历元素。如果我在 ajax 中提醒 url,它会吐出属于该类的最后一个元素的 url。

4

2 回答 2

5

像这样,为了简化你的代码

function successHandler(url, ball) {
  return function(ret) {
     alert('file: ' + url + 'EXXXXXXISTS!!!!!');
     ball.css('color','red')
  }
}

var balls = $('.ball'), requests = []


balls.each(function(index, ball) {
  var url = ...
  requests.push($.ajax({ url : url , success : successHandler(url, ball) })
})

$.when.apply($, requests).done(function() {
  alert('all balls are checked')
}) 

或者使用 ES6:

const success = (url,ball)=>(ret)=>ball.css('color','red')

const balls = $('.balls')
    , reqs = balls.map( (b, i) => {
        const url = ...
        return $.ajax({url, success:success(url,ball)})
    })

$.when.apply($, reqs).done( (resps) => alert('all done'))

一点解释:您this在回调中盲目使用,不知道它将在哪个上下文中执行。为了解决它并将您的 URL 放入回调中,我们正在创建返回函数的函数,因此它将.ball在上下文中具有当前 DOM 对象的 URL。

在完成所有 ajax 请求之后,您可能还需要执行代码,因此 using$.when是最简单的方法。正是因为这个原因,我们才存储了所有的 Promise。

于 2013-05-31T00:01:09.383 回答
0

如果您不关心每个 ajax 调用的执行顺序,并且只想知道它们何时完成并且数组已完全填充,那么您可以通过修复您的引用this并添加回调函数来使其工作完成所有项目后调用:

// this function called when the ajax calls for all balls have finished
// at this point, blogA and blog_count will be populated
function ballsDone() {
    // put your code here
}

var balls = $(".ball");
var cnt = balls.length;
balls.each(function(i){

    var url;
    var self = $(this);

    var c_day = self.data('day');
    var c_mon = self.data('mon');
    var c_year = self.data('year');

    url = c_year + "/" + c_mon + "/" + c_day + ".html";

    $.ajax({

        url: url, 
        error: function()
        {
              alert('file: ' + url + '   does not exist');
              if (--cnt <= 0) {
                  ballsDone();
              }
        },
        success: function()
        {
            blogA[ blog_count ] = url;
            blog_count++;
            self.css("color", "red" );           
            if (--cnt <= 0) {
                ballsDone();
            }
        }
    });
 });

请记住,ajax 调用是异步的,因此您可以使用 ajax 调用结果的唯一位置是在成功处理程序中。您不能在调用之后.each()以同步方式立即使用 ajax 调用的结果,因为 ajax 调用尚未完成。您必须等待成功处理程序被调用,当cnt成功处理程序被调用时,它们都已完成,然后您可以处理结果。

于 2013-05-31T00:36:17.457 回答