【问题标题】:Meteor How to block a method call before the first one is finished?Meteor 如何在第一个方法调用完成之前阻止方法调用?
【发布时间】:2014-12-19 21:17:25
【问题描述】:

我有以下场景:

客户端有一个按钮点击它将在服务器端执行Meteor.call方法,该方法将调用API并获取产品,在此期间我不想禁用此按钮+阻止此方法再次执行基本上没有停止您单击按钮 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};
  }
});

【问题讨论】:

  • 我对 Meteor 并不特别熟悉,但总的来说,您不能阻止调用服务器方法(他们总是可以在控制台中执行此操作)。您可以做的是,在输入getActiveProducts 方法后,首先检查是否设置了某个标志,表明用户已经调用了该函数。如果已设置,请跳过该功能的其余部分。如果未设置,则在返回之前设置并取消设置。
  • @Gerrat 如果流星也是如此,我仍然不确定如何在服务器端启动检查并跳过功能,如果它已执行但尚未完成。另外,如果我有很多按钮/功能,我想可能有一个类似的包,或者如果没有,我将不得不创建一个以简化单行全局功能

标签: meteor


【解决方案1】:

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 秒,或存储该方法在过去一小时内被调用的次数并限制该次数等.

【讨论】:

  • 这种方法存在问题,如果抛出错误,例如Meteor.ErrorgettingProducts 将保持真实,即使它没有真正运行它也会说它是!我当然可以尝试用Meteor.users.update(this.userId, {$set: {gettingProducts: false}}); 覆盖所有错误,但它很容易出错,必须有更好的方法来检测,或者这是最好的方法?
  • 您可以将任何可能在 throw/catch 中引发错误的代码包装起来,然后从那里进行更新。或者只是执行 X 秒方法,该方法不依赖于在方法完成后重置值。
  • 我绝对可以包装每一个错误,但如果它是意外错误,比如我自己的服务器崩溃,任何意外都会导致 X 用户在他的收藏中遇到这个问题,并且网站的可用性有限,所以我认为使用起来并不安全。选项 2. X 秒?我无法真正预测需要多长时间,即使我将其设置为 X 秒,如果服务器没有用户授权的服务 API,我会抛出错误,第一次调用将正确显示错误,但如果再次单击它不会显示任何东西或错误的错误,我认为涵盖所有内容都过于复杂
  • 我已经开始在流星 github 上查找有关 loggingIn() 方法的文件,该方法设置为 true/false,我认为逻辑应该在这种情况下起作用,做这么简单的事情太复杂了。跨度>
  • 经过大量分析,对于我的情况,最好通过删除它们来手动使用收集和覆盖错误
【解决方案2】:

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

【讨论】:

  • 我实际上在寻找持久会话后找到了你的包,我喜欢它,但想发布一个问题来解决几个问题/可能的改进,我想啊,也许我需要的东西不符合你的需要!你发现我的问题真的很有趣! :) 我真的很喜欢它使用真正的集合并且没有黑客它肯定是可靠的,我也喜欢你可以从服务器的用户/集合中读取会话。我不明白连接的东西它是什么连接? 2 个不同的选项卡 = 2 个连接?页面刷新=连接关闭?如果可能,如何克服页面刷新?
  • 连接基本上是每个客户端建立的 DDP 连接。所以你是对的,2 个不同的选项卡意味着 2 个不同的连接。包与连接(而不是像 userId 之类的东西)相关联的原因是会话应该独立于用户帐户工作(最初它用于设置一次性访问 API)。出于速率限制的目的,我认为页面刷新是一个很好的威慑(我不能谈论太多)。随意打开一个问题,我可以进一步研究它:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-11
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
  • 2017-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多