javascript - 在解决之前,我的 jquery $.Deferred 不会阻止另一个 $.ajax 调用的发生

标签 javascript jquery ajax promise jquery-deferred

我正在使用长轮询来检索带有图像 URL 的大型 json 提要。我在我的 $.ajax 请求的 success 部分预加载这些 url,并希望在它们完全加载后调用一个函数来对这些图像执行某些操作。我试图通过在我的 $.ajax 请求的 complete 部分使用 $.Deferred 对象,并解析 $.Deferred 在我的图像预加载循环结束时。

但是,当我监视控制台时,我可以看到在预加载图像时继续进行 $.ajax 调用。 $.Deferred 直到预加载循环结束才解析,所以我不明白为什么会发生这种情况。我对 $.Deferred 的了解有限,但我正在尝试了解更多信息,因此任何关于为什么会发生这种情况以及如何解决此问题的建议都会很棒。我得到的理解是,它们是一种防止函数被调用的方法,直到它们被保留...

作为奖励,除了丑陋的代码之外,发出多个 $.ajax 请求并对返回的数据执行相同的操作是否存在问题?谢谢

$(function(){
    (function poll(){
        var streamUrl = 'http://demofeed';
        var def = $.Deferred();
        console.log('about to get');
        setTimeout(function(){
            $.ajax({
                url: streamUrl,
                dataType: 'json',
                success: function(data) {
                    createArray(data, def);
                },
                complete: function () {
                    $.when(def).done(function() {
                        //Long-poll again
                        poll();
                    });
                },
                error: function(){
                    setTimeout(function(){
                        console.log('There was an error with the XHR Request');
                        poll();
                    }, 3000);
                }
            });
        }, 7000);
    })();
});


function createArray(data, defer){
    console.log('creating array');
    var entries = data['entries'];
    for (var k = 0, j = entries.length; k < j; k++) {
        console.log('there is new media');
        if (entries[k].img) {
            var img = new Image();
            img.onload = (function(entry) {
                return function() {
                    validArray.push(entry);
                    console.log('New Media Loaded');
                }
            })(entries[k]);
            img.onerror = function(){
                console.log('error: bad image source');
            };
            img.src = entries[k].url;
        } else {
            console.log('Not an image');
        }
    }
    defer.resolve(); //Here is where I resolve the deferred object, once for loop is done (all images have been loaded)
}

最佳答案

$.when 等待 promise

您传递给它的是一个延迟对象。它又通过包装转换为 promise ,因此等待它会立即产生它作为值。所以 .when 立即执行。您可以改为使用 def.promise() 来获得它的 promise 。

也就是说,如果我是你,我可能会做一个总体上更 promified 的 API。

var delay = function(ms){
   var def = $.Deferred();
   setTimeout(function(){ def.resolve(); },ms);
   return def.promise();
}

哪个会让我做:

function poll(){
    console.log('about to get');
    return delay(7000).then(function(){
        return $.get('http://demofeed');
    }).then(function(){ // success case
         return createArray(data); // we'll get to it later
    }), function(){ // handle error
          console.log('There was an error with the XHR Request');
          return delay(3000); // wait 3 ms
    }).then(poll); // long poll
}

看它多么清晰,它只有两级缩进,这是因为 promises 链。如果您的代码是顺序的,则大致如下:

  function poll(){
      sleep(7000);
      try{
          var data = $.get('http://demofeed'); // assume this is sync
          arr = createArray(data);
      } catch(e) {
          console.log("There was an error with the XHR Request");
          sleep(3000); 
      }
      poll(); /// call again
  }

至于加载图像功能,考虑在其上使用$.when.apply$.when 等待多个值:

function createImages(data){ // what does this return?
    var promises = data.entries.map(function(entry){
        var img = new Image();
        var d = $.Deferred();
        img.onload = function(entry){ d.resolve(entry); };
        img.onerror = function(){ console.log("Bad Image usage"); }
        return d.promise();
    });
    // this will actually _wait_ for the images now.
    return $.when.apply($, promises); 
}

最后请注意,如果我是你,我会避免使用 jQuery promises 并使用功能更强大的库,如 Bluebird。

关于javascript - 在解决之前,我的 jquery $.Deferred 不会阻止另一个 $.ajax 调用的发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24152332/

相关文章:

javascript - Safari浏览器中的JS/CSS水平鼠标滚轮滚动网站错误

jquery - 当我将 iPad 方向从纵向更改为横向时,页面不断重新加载

处理具有属性的 switch case 的 JavaScript 替代方案

javascript - 如何使用 Pace.JS 在加载期间显示 Div

javascript - 加载时的 Django 微调器 (spin.js)

javascript - 主干中的 SessionStorage 在刷新页面之前不起作用

javascript - JQuery IF 具有多个值显示和隐藏元素

javascript - 字符串文字未附加到 DOM

javascript - 成功回调响应数组长度未定义

Javascript 在第一次完成之前执行第二行代码