2014-12-19 15 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

相关问题