返回此内部Ajax调用JQuery插件进行链接

时间:2018-01-18 05:30:18

标签: javascript jquery ajax recursion

我试图链接我写的一个插件的几个调用。该插件本身有两个可能的Ajax调用 - 内容存储服务以及手柄模板。我对两者都进行了缓存,但是在第一次加载时,卡的顺序经常会发生变化,因为某些调用比前一次调用要长一些。结果,卡的顺序改变,这在内容层次方面是有问题的。在这个例子中,我正在加载标记为研究和播客的卡片。

我按如下方式调用插件:

$('#research').getCards({
    category: 'research',
}).getCards({
    category: 'podcast'
});

该插件非常大,所以我只发布了最后一个Ajax调用(我想要返回它)。一旦从我的服务中获取数据,就会调用fetchTemplate函数,counter为0,length是函数初始化时card_data的长度。我想要这个函数递归,直到我的card_data数组中的每个项目都打印了一张卡片,然后它应该返回这个以允许下一次调用getCards。

$.fn.getCards = function(options) {

    var defaults = {
        target: this,
        category: '',
    },

    settings = $.extend({}, defaults, options);

    function fetchTemplate(card_data, counter, length) {
        counter++;
        var cardTemplate = '';

        if (localStorage[cardTemplate] && settings.localStorageSupport) {
            printCard(localStorage[cardTemplate], card_data[counter - 1]);
            if (counter !== length) {
                fetchTemplate(card_data, counter, length);
            }
        } else {
            $.ajax({
                url: '/templates/cards/' + cardTemplate + '.hbs.js',
                type: 'GET',
                dataType: 'text',
                success: function(data) {
                    localStorage.setItem(cardTemplate, data);
                    printCard(data, card_data[counter - 1]);
                    return this // this is when I want to fire my chained call
                    if (counter !== length) {
                        fetchTemplate(card_data, counter, length);
                    }
                }
            });
        }
    }

};

我尝试过闭包,但这并没有奏效。我也试过return settings.target。最后,我尝试在return this.each中包装整个插件,但是在Ajax请求完成之前,每次触发都没有工作。我知道我可能会重写插件以调用只有一次调用getCards的类别数组,但我不想重写我的所有逻辑。

1 个答案:

答案 0 :(得分:0)

您可以使用.queue().promise()按顺序执行异步任务。

您将context的{​​{1}} $.ajax()调用方法this this作为.then()中的元素,在{{1}定义属性将.data()设置为函数内的数组,并使用异步任务的结果填充数组。设置链this以获取.then()调用的结果,其中$.fn.getCards()将设置为原始jQuery对象,异步任务的结果将在this .data()处访问1}}。然后,您可以再次致电this,重复此过程。

.getCards()
$.fn.getCards = function(options) {
  var el = this;
  if (!this.data().results) {
    this.data().results = [];
  }
  return this.queue("cards", $.map(options, function(item) {
    return function(next) {
      return $.Deferred(function(dfd) {
        setTimeout(function() {
          dfd.resolveWith(el, [item])
        }, 1000)
      })
      .then(function(data) {
        this.data().results.push(data);
        return;
      })
      .then(next)
    }
  })).dequeue("cards").promise("cards")
}

$("body")
.getCards([1,2,3])
.then(function() { 
  console.log(this.data().results, this.get(0).tagName === "BODY"); 
  return this.getCards([4,5,6])
})
.then(function() {
 console.log(this.data().results, this.get(0).tagName === "BODY");
})