jQuery .when()在循环中被忽略了

时间:2016-05-18 13:04:55

标签: javascript jquery ajax loops .when

我有一个自定义循环,需要在进入下一次迭代之前执行一个函数。这是代码:

function customIteration(arr, i)
{
    if (i==arr.length) return;
    var message = arr[i];
    jQuery('#stepTwo #num1StepTwo').html('Expires: ' + $num1);
    jQuery('#stepTwo #num2StepTwo').html(jQuery(message).find('.num2').text());
    jQuery('#stepTwo #num3StepTwo').html(jQuery(message).find('.num3').text());
    i++;
    jQuery.when(mySpecialFunction()).then(customIteration(arr, i));
}

mySpecialFunction():

function mySpecialFunction(){
    return jQuery.ajax({
        url: "https://api.site.com/customurl",
        dataType: "jsonp",
        data: { data1: $data1, data2: $data2 },
        success: function (data) {
            ...some code...
        },
        error: function (e) {
            ...some other code...
        }
    });
}

问题是,我在Fiddler中看到url被上面循环的所有实例立即命中,而没有等待mySpecialFunction()中的ajax代码的响应。这当然会弄乱我应该得到的结果。

2 个答案:

答案 0 :(得分:0)

尝试使用.done()

事实上,

.done()只有成功回调。

.then()同时有成功和失败的回调。

从jQuery 1.8开始,deferred.then()方法返回一个新的promise,它可以通过函数过滤延迟的状态和值,替换现在已弃用的deferred.pipe()方法。

deferred.done()方法接受一个或多个参数,所有参数都可以是单个函数或函数数组。

由于deferred.done()返回延迟对象,因此延迟对象的其他方法可以链接到此方法,包括其他.done()方法。解析Deferred后,将按照添加顺序使用提供给resolve或resolveWith方法调用的参数执行doneCallbacks。

答案 1 :(得分:0)

尝试使用.done()和递归函数,应该更容易实现和理解。 像这样:

import { Meteor } from 'meteor/meteor';
import { Counts } from 'meteor/tmeasday:publish-counts';

import { Parties } from './collection';

if (Meteor.isServer) {
  Meteor.publish('parties', function(options, searchString) {
    const selector = {
      $or: [{
        // the public parties
        $and: [{
          public: true
        }, {
          public: {
            $exists: true
          }
        }]
      }, {
        // when logged in user is the owner
        $and: [{
          owner: this.userId
        }, {
          owner: {
            $exists: true
          }
        }]
      }]
    };

    if (typeof searchString === 'string' && searchString.length) {
      selector.name = {
        $regex: `.*${searchString}.*`,
        $options : 'i'
      };
    }

    Counts.publish(this, 'numberOfParties', Parties.find(selector), {
      noReady: true
    });

    return Parties.find(selector, options);
  });
}

这样做是为了确保您的单次迭代在再次调用自身并继续迭代之前结束。 所以基本上你的函数在完成一次迭代时调用自身,并一直持续到一切都被迭代,然后停止。