2014-12-19 13 views
0

我有以下情形:流星如何在第一個完成前阻止方法調用?

客戶端有一個按鈕,點擊它會在服務器端,將調用API,並獲取產品執行Meteor.call方法,在這期間我wan't禁用此按鈕+阻止此方法再次執行基本上沒有任何東西阻止你點擊100倍的按鈕,並且服務器將一直保持執行相同的方法。

一些想法,我在我的腦海:使用會話禁用按鈕(問題:仍然可以使用控制檯Meteor.call和濫用它) 我也是在文檔看着Meteor.applywait:true沒有似乎阻止方法執行。我真的不知道如何處理這種事情,沒有黑客。

客戶端:

'click .button-products': function(e){ 
    Meteor.call('getActiveProducts', function(error, results){ 
     if (error) 
     return Alerts.add(error.reason, 'danger', {autoHide: 5000}); 
     if (results.success) 
     return Alerts.add('Finished Importing Products Successfully', 'success', {autoHide: 5000}); 
    }) 
    } 

服務器端

Meteor.methods({ 
    getActiveProducts: function(){ 
    var user = Meteor.user(); 
    var api = api.forUser(user); 

    importProducts = function(items){ 
     nextPage = items.pagination.next_page; 
     items.results.forEach(function(product){ 
     var sameproduct = apiProducts.findOne({listing_id: product.listing_id}); 
     if (sameproduct) { 
      return; 
     } 
     var productExtend = _.extend(product, {userId: Meteor.userId()}); 
     apiProducts.insert(productExtend); 
     }); 
    }; 

    var products = api.ProductsActive('GET', {includes: 'Images', limit: 1}); 
    importProducts(products); 
    while (nextPage !== null) { 
     products = api.ProductsActive('GET', {includes: 'Images', page: nextPage, limit: 1}); 
     importProducts(products); 
    } 
    return {success: true}; 
    } 
}); 
+1

我不熟悉,流星明確,但在一般情況下,你**不能**防止被稱爲服務器方法(他們總能做到在控制檯)。你可以做什麼,在進入'getActiveProducts'方法時,首先檢查是否設置了一個指示用戶已經調用該函數的特定標誌。如果已設置,則跳過該功能的其餘部分。如果沒有設置,請在返回之前將其設置並取消設置。 – Gerrat

+0

@Gerrat如果流星也是如此,我還不確定如何在服務器端啓動檢查並跳過功能,如果它已經執行並且尚未完成。另外,如果我有很多按鈕/功能,我猜可能有一個類似的東西,如果沒有,我將不得不創建一個,使其容易一行全局功能 – zumbamusic

回答

0

From the Meteor docs

在服務器上,從給定的客戶端運行一次一個方法。直到第N次調用返回,客戶端的第N + 1次調用纔會啓動。但是,您可以致電this.unblock來更改此設置。這將允許第N + 1個調用開始在新光纖中運行。

這意味着後續的方法調用實際上並不知道它們是在第一次調用仍在運行時產生的,因爲第一次調用已經完成。但是你可以做這樣的事情:

Meteor.methods({ 
    getActiveProducts: function() { 
    var currentUser = Meteor.users.findOne(this.userId); 
    if (currentUser && !currentUser.gettingProducts) { 
     Meteor.users.update(this.userId, {$set: {gettingProducts: true}}); 

     // let the other calls run, but now they won't get past the if block 
     this.unblock(); 

     // do your actual method stuff here 

     Meteor.users.update(this.userId, {$set: {gettingProducts: false}}); 
    } 
    } 
}); 

現在後續調用可以運行,而第一仍在運行,但不會運行if塊內部的任何物件。理論上,如果用戶發送了足夠多的呼叫,第一個呼叫可以在所有其他呼叫開始之前完成。但是這應該至少大大限制可以由用戶發起的etsy呼叫的數量。您可以使這種技術更加健壯,如存儲上次啓動成功的呼叫並確保X秒已經過去,或存儲方法在最近一小時內被呼叫的次數並限制該號碼等。

+0

這種方法存在問題,如果一個錯誤被拋出這樣的'Meteor.Error' getsProducts將保持真實,即使它沒有真正運行,它會說這是!我當然可以試着用'Meteor.users.update(this.userId,{$ set:{gettingProducts:false}})來覆蓋每個錯誤;'但它有點容易出錯,必須有更好的方法來檢測到或最好的可以是? – zumbamusic

+0

你可以包裝任何可能在throw/catch中拋出錯誤的代碼,並從那裏進行更新。或者,只需執行方法結束後不依賴於重置值的X秒方法即可。 – sbking

+0

我可以絕對包裝每一個錯誤,但如果它是意外的錯誤,無論如何,像我自己的服務器崩潰,任何意想不到的事情都會導致X用戶被困在他的收藏中,並限制網站的可用性,所以我認爲它不是真正安全的使用。選項2. X秒?我真的不能預測它需要多少時間,即使我將它設置爲X秒,如果服務器沒有用戶授權的服務API,我會拋出一個錯誤,第一次調用將會正確顯示錯誤,但如果再次單擊它將不會顯示任何事情或錯誤的錯誤,我認爲涵蓋所有內容已經過於複雜了 – zumbamusic

0

一個package I wrote前陣子可能會派上用場你。本質上,它暴露在服務器端的會話API(因此得名),這意味着你可以做類似的調用中ServerSession.set('doingSomethingImportant', true),然後在後續調用檢查該會話的值。這次會議只能在服務器上進行設置,並在連接關閉過期(所以他們垃圾電話,但只有一樣快,因爲他們可以刷新頁面)。 如果發生錯誤,您可以重置會話。不應該有任何與意外錯誤有關的問題,因爲會話只會在連接關閉時過期。讓我知道你在想什麼:)

+0

在尋找持久會話後,我實際上已經找到了您的軟件包,但我希望發佈幾個問題/可能的改進和想法也許我需要的東西不符合你的需求!你發現我的問題真的很有趣! :)我真的很喜歡這是使用真正的收藏和沒有黑客它肯定會是可靠的,我也喜歡你可以從用戶/設置從服務器讀取會話。我不明白連接的事情是什麼連接? 2個不同的標籤= 2個連接?頁面刷新=連接關閉?如果可能,如何克服頁面刷新? – zumbamusic

+0

連接基本上是每個客戶端建立的DDP連接。所以你是正確的,2個不同的標籤將意味着2個不同的連接。包與連接綁定(而不是像userId)的原因是會話應該獨立於用戶帳戶(最初用於設置一次性訪問API)。出於限制速度的目的,我認爲頁面刷新是一個很好的威懾力量(我不能說太多的話)。儘管如此,請隨時打開一個問題,我可以進一步研究它:) – mark

相關問題