Meteor如何在第一个方法调用完成之前阻止方法调用?

时间:2014-12-19 21:17:25

标签: meteor

我有以下情况:

客户端有一个单击它的按钮将在服务器端执行Meteor.call方法,该方法将调用API并获取产品。在此期间,我不想禁用此按钮+阻止此方法执行再次基本上没有什么能阻止你点击按钮100次,服务器将继续一次又一次地执行相同的方法。

我的想法很少:使用会话来禁用按钮(问题:仍然可以使用控制台Meteor.call并滥用它) 我还查看了文档中的Meteor.apply wait: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};
  }
});

2 个答案:

答案 0 :(得分:0)

From the Meteor docs

  

在服务器上,来自给定客户端的方法一次运行一个。来自客户端的第N + 1次调用不会开始,直到第N次调用返回。但是,您可以通过调用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秒已过,或存储在过去一小时内调用该方法的次数并限制该数量等

答案 1 :(得分:0)

前一阵package I wrote可能会派上用场。本质上它暴露了服务器端的Session api(因此名称),这意味着您可以在调用中执行ServerSession.set('doingSomethingImportant', true)之类的操作,然后在后续调用中检查此会话的值。该会话只能在服务器上设置,并在连接关闭时到期(因此他们可以垃圾邮件调用,但只能刷新页面的速度)。 如果出现错误,您只需重置会话即可。不应该出现任何与意外错误相关的问题,因为会话将在连接关闭时到期。让我知道你的想法:)。