流星:为什么Iron Router的onBeforeAction会被多次调用? [英] Meteor: Why is Iron Router's onBeforeAction called multiple times?

查看:53
本文介绍了流星:为什么Iron Router的onBeforeAction会被多次调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在浏览器中访问路线时,我希望Iron Router在加载路线之前先调用onBeforeAction.但是,似乎在首次加载路线时被调用了3次.

When I visit a route in my browser I expect Iron Router to call onBeforeAction once before loading the route. But it looks like it is being called 3 times when first loading the route.

这对我来说是个问题,因为如果用户无权访问该文档,我想放置重定向用户的代码.

This is an issue for me because I want to put code that redirects the user if they do not have access to that document.

onBeforeAction: ->
  console.log 'called once' #Called 3 times when first loading the route!
  thread = Research.findOne(@params._id)
  console.log thread # This is undefined at first run
  thread = Research.findOne(@params._id)
  if thread?
    Meteor.subscribe 'collabUsers', @params._id
  else
    Router.go '/research'

由于多次调用,因此导致重定向问题.确实具有访问权限的第一个用户也将被重定向,因为最初的线程是未定义的.

Since it is called multiple times, it causes issues with redirecting. First users that do have access are also redirected because at first thread is undefined.

如果要检查用户是否有权访问路由所依赖的数据,我要怎么做,如果没有,我就需要重定向用户.因此,这就是为什么在onBeforeAction中,我试图从数据库中提取文档,如果文档存在,则将加载页面,否则将重定向或向用户抛出错误消息.

What I am trying to do if check if the user has access to the data the route depends on, if not then I need to redirect the user. So that is why in onBeforeAction I am trying to pull a document from database and if it exists then I will load the page or else I will redirect or throw and error message at the user.

但是我注意到onBeforeAction中的console.log语句在第一次加载路由时被调用了3次.而且在首次运行时,由于某种原因,用户无法访问任何研究线程(我认为尚未设置订阅,并且首次运行时无法访问文档),这导致我尝试查看他们是否具有访问权限时出现了问题文档,因为在第一次运行时没有人可以访问.

But I notice that the console.log statement in onBeforeAction is called 3 times when the route is first loaded. And also on the first run the user does not have access to any research threads for some reason (I believe the subscription has not been setup and documents are not accessible on first run) So that causes issues with my trying to see if they have access to the document because on first run nobody has access.

这是整个路由器.咖啡代码

Here is the entire router.coffee code

appendUserData = (array) ->
  _.each array, (item) ->
    user = Meteor.users.findOne(item.userId)
    if user?.profile.firstName? && user?.profile.lastName?
      item.firstName = user.profile.firstName
      item.lastName = user.profile.lastName
      item.username = user.username

userEnabled = () ->
  if Meteor.user()
    if $(window).width() > 768
      if !$('.show-left').hasClass 'active'
        Meteor.defer ->
          $('.show-left').click()

requireLogin = (pause) ->
  if !Meteor.user()
    @setLayout 'layoutLoggedOut'
    if Meteor.loggingIn()
      @render @loadingTemplate
    else
      @render 'login'
      pause()
  else
    @setLayout 'layout'
    if window.location.pathname is '/' or undefined
      Router.go('addAndSearchPosts')
    else
      Router.go(window.location.pathname)

Router.configure 
  layoutTemplate: 'layout'
  loadingTemplate: 'loading'
  onBeforeAction: ->
    #this code get which ids we need to get data from to render template. Here we need to get data to notification of collab
    params = {}
    params.threadIds = []
    params.userIds = []
    notifications = Notifications.find {userId: Meteor.userId()}
    notifications.forEach (notification) ->
      params.threadIds.push notification.threadId
      params.userIds.push notification.requesterId

    @subscribe('notificationDataCollab', params).wait()
  waitOn: ->
    [
      Meteor.subscribe 'myResearch', Meteor.userId()
      Meteor.subscribe "notifications"
    ]


Router.onAfterAction userEnabled
Router.onBeforeAction requireLogin,
  except: 'template1'
Router.onBeforeAction 'loading'
Router.onBeforeAction ->
  Errors.clearSeen()

Router.map ->
  @route 'posts_page',
    path: '/posts',
  @route 'template1',
    path: '/template1',
  @route 'login',
    path: '/',
  @route 'addAndSearchPosts',
    path: '/bookmarks',
    waitOn: ->
      Meteor.subscribe 'myBookmarks', Meteor.userId()
    data: ->
      bookmarks: Bookmarks.find
        _userId: Meteor.userId()
  @route 'research',
    path: '/research/:_id',
    waitOn: ->
      [
        Meteor.subscribe 'threadNotes', @params._id, Meteor.userId()
        Meteor.subscribe 'collabUsers', @params._id
      ]
    onBeforeAction: ->
      console.log 'called once'
      #Meteor.subscribe 'collabUsers', @params._id
      # thread = Research.findOne(@params._id)
      # console.log thread
      #thread = Research.findOne(@params._id)
      # if thread?
      #   Meteor.subscribe 'collabUsers', @params._id
      # else
      #   Router.go '/research'
        #Errors.throw('Thread does not exist or you do not have access', false)
    data: ->
      # this code is for appending the user data to pending and current collaborators for this thread
      thread = Research.findOne(@params._id)
      if thread?.pending?.collaborators?.length > 0
        appendUserData(thread.pending.collaborators)
      if thread?.collaborators?.length > 0
        appendUserData(thread.collaborators)
      data = 
        researchThread: thread,
        notes: Notes.find
          _threadId: @params._id
        ,
          sort: 
            date: -1
      data
  @route 'researchHome',
    path: '/research'
  @route 'profileEdit',
    path: '/editprofile'

这是Publications.coffee

Here is publications.coffee

Meteor.publish 'myResearch', (id) ->
  Research.find({$or: [{_userId: id}, {'collaborators.userId': id}] })


Meteor.publish 'threadNotes', (threadId) ->
  Notes.find({_threadId: threadId})

Meteor.publish 'myBookmarks', (userId) ->
  Bookmarks.find({_userId: userId})

Meteor.publish 'collabUsers', (threadId) ->
  Meteor.users.find({}, {fields: {profile: 1, username: 1}})

Meteor.publish 'notifications', ->
  Notifications.find()

Meteor.publish 'notificationDataCollab', (params) ->
  [
    Meteor.users.find({_id: {$in: params.userIds}}, {fields: {username: 1}})
    Research.find({_id: {$in: params.threadIds}}, {fields: {name: 1}})
  ]

对于如何处理此问题的任何建议,我们深表感谢.

Any advice on how to handle this is appreciated.

推荐答案

onBeforeAction会运行并以反应方式重新运行.您可能需要onRun.

onBeforeAction is run and rerun reactively. You probably want onRun.

这篇关于流星:为什么Iron Router的onBeforeAction会被多次调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆