簡體   English   中英

javascript / jquery:迭代調用函數; 等到上一個通話結束

[英]javascript/jquery: Iterative called function; wait till the previous call is finished

我對每個項目上的函數調用庫有一些問題。 我必須通過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(),then()等的信息,但實際上並不清楚如何實現這一點。

非常感謝每個可以幫助我的人:)

控制庫的最簡單,最骯臟的方法是覆蓋它們的方法

但是我真的不知道核心問題,所以下面有其他提示

如果您可以控制checkState,那么只需收集數據並在服務器端更改控制器即可使用數組

並且如果您不知道何時將調用下一個checkState來對您的集合進行計數,並使請求使用setTimeout在一段時間后檢查集合,或者使用setIterval對其進行連續檢查

如果你不希望得到相同的項目進行了多次然后存儲在像一些變量托運物品alreadyChecked ,使搜索請求在這個項目之前alreadyChecked

當某個圖書館正在使用您的物品時,您會收到通知,請使用getter ,然后收集您的物品。 當您收集到足夠的項目時,您可以提出請求,但是當您沒有足夠的項目時,請使用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;
  } });
}

庫現在在每個項目上調用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);
        });
});

執行新功能將使您在最后一分鍾內使用這些參數發出的最后一個請求中調用這些參數,或者發出新請求

您可以使用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); });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM