2012-08-28 43 views
1

在一些地方,我們必須只有一個功能運行的實例。信號量,run_once裝飾器,或類似的東西

此代碼的工作對我來說:

function example() { 
    var that = this; 
    if(that.running) { 
     return false; 
    } 
    that.running = true; 
    $.get(url, {}, function (data) { 
     that.running = false; 
    }); 
} 

我們如何能夠改善它,並使它更具重用性?

UPD這裏是解決方案的基礎上,弗裏茨麪包車坎彭答案:

function make_run_once(callback) { 
    callback.running = false; 
    return function() { 
     if(callback.running) { 
      return false; 
     } 
     callback.running = true; 
     deferred = $.Deferred(); 
     deferred.done(function() { 
      callback.running = false; 
     }); 
     callback(deferred); // pass deferred to callback so it can resolve at it's own leisure 
    }; 
} 
+0

你的目標是真的有**功能**只運行一次,或者你是否試圖阻止來自同一個對象的多個Ajax **請求? –

+0

你基本上使用this.running。這並不一定意味着你有一個正在運行的函數實例,每個實例只有一個實例。如果總共只需要一個實例,那麼使用example.running(如果示例是頂層函數而不是內部函數)或window.running(儘管如此,儘量避免命名衝突)。 –

+0

@Chris,實際上,我有計算,這是前後ajax調用,所以我想阻止整個函數運行。同時也阻止可能的答案 - 我不'異步:false':) –

回答

2

你可能想使用jQuery's `Deferred' functionality爲:

function decorate(fn) { 
    var deferred; 
    return function(){ 
     if (!deferred) { 
      deferred = new jQuery.Deferred; 
      fn(deferred.resolve); // pass in the callback 
     } 
     return deferred; 
    }; 
} 

一個裝飾功能將始終返回相同的遞延對象,這將與原函數的回調來解決 - 開始第一次調用。

+0

解決延期問題時,此功能不會「重置」。我認爲這是一個要求。 – Halcyon

+0

是的,我在問題標題中讀到了「run_once」,並認爲這將是需要的。如果你想重置它,你可以爲deferred.state()==「resolved」添加一個檢查 – Bergi

0

像這樣的事情?

function make_run_once(callback) { 
    var deferred = false; 
    return function() { 
     if (false === deferred) { 
      return; 
     } else { 
      deferred = $.Deferred(); 
      deferred.done(function() { 
       deferred = false; 
      }); 
      callback(deferred); // pass deferred to callback so it can resolve at it's own leisure 
     } 
    }; 
} 

var once = make_run_once(function (deferred) { 
    // do stuff, possible ajax stuff 
    setTimeout(function() { 
     deferred.resolve(); // resolve at some point so it become unblocked again 
    }, 100); 
}); 
once(); // run 
once(); // block 
once(); // block 
once(); // block 
setTimeout(once, 500); // run 

請求'取代'其他請求,你有嗎?像一個自動完成的功能。你需要修改它才能使其工作。不要忽略新的請求,你應該保留最新的請求,並在最後一個請求完成時觸發它。

+1

看起來令人困惑的延期同名變量和$ .Deferred對象的原因。在當前示例中也不會創建延遲對象。 –

相關問題