在数组中为jQuery promise添加ajax会导致意外行为

时间:2015-09-15 12:25:15

标签: javascript jquery ajax

我有一个each语句,它会发出单独的AJAX请求,并将它们添加到如下数组中:

var promises = [];

$items.each(function(k, v) {
   promises.push(
      $.ajax({
         url: ...,
         .... 
      }) 
   );
});


$.when.apply($, promises).done(function() { ... });

似乎,我不知道原因,第一次加载页面时,或者部署时(我使用ASP.NET MVC),ajax已经为第一个项目执行了这个断点:

promises.push($.ajax ...

如果我刷新页面,那么一切正常,$.when正确执行ajax请求。但是,如果我部署应用程序,则问题仍然存在。

为什么第一次调用了ajax请求(不在$,.when中)?我的错误在哪里?我在JavaScript中没有错误。

1 个答案:

答案 0 :(得分:0)

如果代码不比示例复杂,你可以这样做

var get_promises = function() {
    var promises = [];
    return function () {
        if (promises.length === 0) {
            $items.each(function(k, v) {
               promises.push(
                  $.ajax({
                     url: ...,
                     .... 
                  }) 
               );
            });
        }
        return promises;
    }
}());
$.when.apply($, get_promises()).done(function() { ... });
  

我无法相信我建议如下!!但是我要拥有它:D

做你想做的事的一种方法是所谓的"懒惰"许

Promise / A + polyfill - 主要用于Internet Explorer(包括11-Edge,或者在Windows 10中调用的任何内容,具有本机Promise)

<script src="https://www.promisejs.org/polyfills/promise-6.1.0.js"></script>

基于 - https://github.com/then/lazy-promise的延迟承诺实施 - 但已修改为与浏览器本机承诺一起使用 - 请注意,仅在firefox中测试,YMMV

var inherits = (function() {
    if (typeof Object.create === 'function') {
        return function inherits(ctor, superCtor) {
            ctor.super_ = superCtor
            ctor.prototype = Object.create(superCtor.prototype, {
                constructor: {
                    value: ctor,
                    enumerable: false,
                    writable: true,
                    configurable: true
                }
            });
        };
    } else {
        return function inherits(ctor, superCtor) {
            ctor.super_ = superCtor;
            var TempCtor = function () {};
            TempCtor.prototype = superCtor.prototype;
            ctor.prototype = new TempCtor();
            ctor.prototype.constructor = ctor;
        };
    }
}());

inherits(LazyPromise, Promise);

function LazyPromise(fn) { 
    var promise;
    if (!(this instanceof LazyPromise)) {
        return new LazyPromise(fn);
    }
    if (typeof fn != 'function') {
        throw new TypeError('fn is not a function');
    }

    this.then = function(onResolved, onRejected) {
        return (promise = promise || new Promise(function(resolve, reject) {
            setTimeout(function() {
                try { fn(resolve, reject) }
                catch (e) { reject(e) }
            }, 0);
        })).then(onResolved, onRejected);
    };
}

现在改变你的代码 - 非常小

var promises = [];

$items.each(function(k, v) {
   promises.push(
      new LazyPromise(function(resolve, reject) { // wrap the (broken) jQuery "promise" in a Lazy Promise
          $.ajax({
             url: ...,
             .... 
          })
          .then(resolve, reject); // I assume $.ajax is "thenable", so resolve the wrapping Lazy promise;
      }) // end of Lazy Promise wrapper
   );
});

$.when.apply($, promises).done(function() { ... });

这可能有点矫枉过正,但它应该完全符合您在问题中的要求