javascript / jquery:迭代调用函数;等到上次通话结束

时间:2016-08-11 21:03:47

标签: javascript jquery

我在每个项目上调用函数的库存在一些问题。我通过ajax请求检查此项目的状态,并且不想为每个项目调用一个请求,但获取一系列项目状态。 因为这些项目是日期,我可以很容易地得到一些范围 - 这是很好的部分:)

所以要给出一些代码......

var itemStates = {};

var libraryObj = {
    itemCallback: function(item) {
        return checkState(item);
    }
}

function checkState(item) {
    if(!itemStates.hasOwnProperty(item)) {
        $.get('...', function(result) {
            $.extend(true, itemStates, result);
        });
    }

    return itemStates[item];
}

库现在正在每个项目上调用library.itemCallback(),但是我想在再次调用checkState()之前等待checkState()中发出的请求(因为下一个项目的状态非常高)已经在上一个请求中提出要求。

我读到了defer和wait(),然后是()等等,但是我们真的不知道如何实现它。

非常感谢所有能帮助我的人:)

3 个答案:

答案 0 :(得分:0)

控制库的最简单和最简单的方法是覆盖它们的方法

但我真的不知道核心问题,所以其他提示在下面

如果您可以控制checkState,那么只需收集数据并更改服务器端的控制器即可使用数组

如果您不知道何时调用下一个checkState来计算您的集合并使请求使用setTimeout在一段时间后检查集合或使用setIterval连续检查它

如果您不想多次获得相同的商品,请将已检查的商品存储在某个变量中,例如alreadyChecked,然后在alreadyChecked

中请求搜索此商品

当某个图书馆使用您的项目使用getter时收到通知, 然后收集你的物品。 当您收集到足够的物品时,您可以提出要求, 但是当你没有enought项目时,请使用setTimeout并等待一段时间。如果没有任何变化,则表示库现在完成迭代,您可以使用剩下的项目发出请求。

let collection=[];// collection for request
let _items={};// real items for you when you don't want to perfrom actions while getting values
let itemStates={};// items for library
let timeoutId;
//instead of itemStates[someState]=someValue; use
function setItem(someState,someValue){

  Object.defineProperty(itemStates, someState, { get: function () {
    if(typeof timeoutId=="number")clearTimeout(timeoutId);
    //here you can add someState to the collection for request
    collection.push(_items[someState]);
    if(collection.length>=10){
      makeRequest();
    }else{
      timeoutId=setTimeout(()=>{...checkCollectionAndMakeRequest...},someTime);
    }
    return someValue;
  } });
}

答案 1 :(得分:0)

  

库现在正在每个项目上调用library.itemCallback(),但是我想在再次调用checkState()之前等待checkState()中发出的请求(因为下一个项目的状态已经非常高了)在上一个请求中提出要求。

我能想到的一件事是制作一些缓存功能,具体取决于调用函数的最后时间返回上一个值或发出新请求

var cached = function(self, cachingTime, fn){
    var paramMap = {};

    return function( ) {

        var arr = Array.prototype.slice.call(arguments);
        var parameters = JSON.stringify(arr);
        var returning;

        if(!paramMap[parameters]){

           returning = fn.apply(self,arr);       
           paramMap[parameters]={timeCalled: new Date(), value:returning};

        } else  {

           var diffMs = Math.abs(paramMap[parameters].timeCalled - new Date());
           var diffMins = ( diffMs / 1000 ) / 60;

           if(diffMins > cachingTime){

               returning = fn.apply(self,arr);       
               paramMap[parameters] = {timeCalled: new Date(), value:returning};    

           } else {

              returning = paramMap[parameters].value;

            }

        }

        return returning;
    }
}

然后你将ajax调用包装到你已经创建的函数中

var fn = cached(null, 1 , function(item){
        return $.get('...', function(result) {
            $.extend(true, itemStates, result);
        });
});

执行新函数将为您提供最后一个承诺,这些承诺在最后一分钟内使用这些参数进行的最后一次请求中调用这些参数或发出新请求

答案 2 :(得分:0)

您可以使用jQuery.DeferredJavascript Promise来实现此目的。在以下代码中,itemCallback()将等待之前的调用完成,然后再调用checkState()

var queue = [];
var itemStates = {};

var libraryObj = {
  itemCallback: function(item) {
    var def = $.Deferred();
    $.when.apply(null, queue)
      .then(function() {
        return checkState(item);
      })
      .then(function(result) {
        def.resolve(result);
      });
    queue.push(def.promise());
    return def.promise();
  }
}

function checkState(item) {
  var def = $.Deferred();
  if (!itemStates.hasOwnProperty(item)) {
    $.get('...', function(result) {
      $.extend(true, itemStates, result);
      def.resolve(itemStates[item]);
    });
  } else
    def.resolve(itemStates[item]);
  return def.promise();
}

//these will execute in order, waiting for the previous call
libraryObj.itemCallback(1).done(function(r) { console.log(r); });
libraryObj.itemCallback(2).done(function(r) { console.log(r); });
libraryObj.itemCallback(3).done(function(r) { console.log(r); });
libraryObj.itemCallback(4).done(function(r) { console.log(r); });
libraryObj.itemCallback(5).done(function(r) { console.log(r); });

使用Javascript Promises

构建的相同示例
var queue = [];
var itemStates = {};

var libraryObj = {
  itemCallback: function(item) {
    var promise = new Promise(resolve => {
      Promise.all(queue)
        .then(() => checkState(item))
        .then((result) => resolve(result));
    });
    queue.push(promise);
    return promise;
  }
}

function checkState(item) {
  return new Promise(resolve => {
    if (item in itemStates)
      resolve(itemStates[item]);
    else {
      $.get('...', function(result) {
        $.extend(true, itemStates, result);
        resolve(itemStates[item]);
      });
    }
  });
}

//these will execute in order, waiting for the previous call
libraryObj.itemCallback(1).then(function(r) { console.log(r); });
libraryObj.itemCallback(2).then(function(r) { console.log(r); });
libraryObj.itemCallback(3).then(function(r) { console.log(r); });
libraryObj.itemCallback(4).then(function(r) { console.log(r); });
libraryObj.itemCallback(5).then(function(r) { console.log(r); });