【问题标题】:How to make onBeforeAction call wait until a function call inside finishes in meteor.js?如何使 onBeforeAction 调用等到内部的函数调用在meteor.js中完成?
【发布时间】:2015-11-02 17:02:43
【问题描述】:

我有一个与 meteor.js 同步的 onBeforeAction 方法

Router.onBeforeAction(function() {
    var self;

    self = this;

    authToken = Session.get('authToken');

   if (!authToken) {
       this.redirect('login');
       this.next();
   } else {
       Meteor.call('validateAuthToken', authToken, function (error, result)) {
           if (result) {
               self.next();
           } else {
               self.redirect('login');
               self.next();
           }
       }
   }
});

我需要通过调用服务器调用来验证存储在 Session 中的身份验证令牌。但是这个方法在我执行的时候总是会抛出异常。我发现原因是 onBeforeAction 调用在 validateAuthToken 调用返回之前终止。因此 self.next() 不会采取行动。所以我想知道我能做些什么来防止 onBeforeAction 调用停止,直到 validateAuthToken 返回验证结果然后继续?


我通过等待会话变量尝试了不同的实现,但似乎就绪状态从未设置为 true

Router.onBeforeAction(function() {
    var authToken;

    authToken = Session.get('authToken');

    if (!authToken) {
        this.redirect('login');
        this.next();
    } else {
        Meteor.call('validateAuthToken', authToken, function (error, result) {
            if (!error) {
                Session.set("tokenValidated", result);
            }
        });

        this.wait(Meteor.subscribe('token', Session.get('tokenValidated')));
        if (this.ready()) {
            if (!Session.get("tokenValidated")) {
                this.redirect('login');
                this.next();
            } else {
                this.next();
            }
        }
    }

});

【问题讨论】:

    标签: meteor frontend javascript iron-router


    【解决方案1】:

    编辑:在处理了这个问题一点点之后,我想出了一个工作示例(没有无限循环)。您可以使用以下代码:

    Util = {};
    
    // We need to store the dep, ready flag, and data for each call
    Util.d_waitOns = {};
    
    // This function returns a handle with a reactive ready function, which
    // is what waitOn expects. waitOn will complete when the reactive function
    // returns true.
    Util.waitOnServer = function(name) {
      // This prevents the waitOnServer call from being called multiple times
      // and the resulting infinite loop.
      if (this.d_waitOns[name] !== undefined &&
          this.d_waitOns[name].ready === true) {
        return;
      }
      else {
        this.d_waitOns[name] = {};
      }
      var self = this;
      // We need to store the dependency and the ready flag.
      this.d_waitOns[name].dep = new Deps.Dependency();
      this.d_waitOns[name].ready = false;
    
      // Perform the actual async call.
      Meteor.call(name, function(err, or) {
        // The call has complete, so set the ready flag, notify the reactive
        // function that we are ready, and store the data.
        self.d_waitOns[name].ready = true;
        self.d_waitOns[name].dep.changed();
        self.d_waitOns[name].data = (err || or);
      });
    
      // The reactive handle that we are returning.
      var handle = {
        ready: function() {
          self.d_waitOns[name].dep.depend();
          return self.d_waitOns[name].ready;
        }
      };
      return handle;
    }
    
    // Retrieve the data that we stored in the async callback.
    Util.getResponse = function(name) {
      return this.d_waitOns[name].data;
    }
    

    从 waitOn 中调用如下:

    Router.route("/test", {
      name: "test",
      action: function() {
        console.log("The data is ", Util.getResponse("testWaitOn"));
      },
      waitOn: function() {
        return Util.waitOnServer("testWaitOn");
      }
    })
    

    我写了一篇博文,里面有更深入的解释,你可以在这里找到:

    http://www.curtismlarson.com/blog/2015/05/04/meteor-ironrouter-waitOn-server/

    【讨论】:

    • 我尝试了这个实现,但似乎由于某种原因我陷入了无限循环
    • 如果您在 login 页面上,我可以看到这会如何陷入无限循环。我在Router.onBeforeAction 中添加了except
    • 它仍然是一个无限循环,从任何路线开始
    【解决方案2】:

    你也可以使用https://github.com/iron-meteor/iron-router/issues/426这个代码sn-p

    Ready = new Blaze.ReactiveVar(false);
    Router.route('feed',{
      waitOn: function () {
        Meteor.call('getInstagramUserFeed', function(error, result) {
          if(!error) Ready.set(result)
        });
        return [
          function () { return Ready.get(); }
        ];
      },
      action: function () {
        if (this.ready()) this.render('feed')
        else this.render('LoadingMany');
      }
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-11
      • 1970-01-01
      • 2016-01-31
      • 2016-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多