gpt4 book ai didi

javascript - Meteor Iron 路由器钩子(Hook)被多次运行

转载 作者:行者123 更新时间:2023-11-30 00:32:14 25 4
gpt4 key购买 nike

编辑: Here 是 github 存储库。您可以测试网站 here

在主页上,只需打开浏览器控制台,您就会注意到 WaitOndata 被运行了两次。当没有WaitOn时,数据只运行一次。


我已经通过扩展 RouteController 并进一步扩展这些 Controller 来设置我的页面。例如:

    ProfileController = RouteController.extend({
layoutTemplate: 'UserProfileLayout',
yieldTemplates: {
'navBarMain': {to: 'navBarMain'},
'userNav': {to: 'topUserNav'},
'profileNav': {to: 'sideProfileNav'}
},
// Authentication
onBeforeAction: function() {
if(_.isNull(Meteor.user())){
Router.go(Router.path('login'));
} else {
this.next();
}
}
});

ProfileVerificationsController = ProfileController.extend({
waitOn: function() {
console.log("from controller waitOn");
return Meteor.subscribe('userProfileVerification');
},

data: function() {
// If current user has verified email
console.log("from controller data start");
var verifiedEmail = Meteor.user().emails && Meteor.user().emails[0].verified ? Meteor.user().emails[0].address : '';
var verifiedPhoneNumber = Meteor.user().customVerifications.phoneNumber && Meteor.user().customVerifications.phoneNumber.verified ? Meteor.user().customVerifications.phoneNumber.number : '';

var data = {
verifiedEmail: verifiedEmail,
verifiedPhoneNumber: verifiedPhoneNumber
};
console.log("from controller data end");
return data;
}
});

观察客户端的控制台,似乎 Hook 运行了 2-3 次。而且我也有一次收到错误消息,因为数据不可用。下面是只请求一次页面的控制台:

from controller waitOn
profileController.js?966260fd6629d154e38c4d5ad2f98af425311b71:44 from controller data start
debug.js:41 Exception from Tracker recompute function: Cannot read property 'phoneNumber' of undefined
TypeError: Cannot read property 'phoneNumber' of undefined
at ProfileController.extend.data (http://localhost:3000/lib/router/profileController.js?966260fd6629d154e38c4d5ad2f98af425311b71:46:62)
at bindData [as _data] (http://localhost:3000/packages/iron_controller.js?b02790701804563eafedb2e68c602154983ade06:226:50)
at DynamicTemplate.data (http://localhost:3000/packages/iron_dynamic-template.js?d425554c9847e4a80567f8ca55719cd6ae3f2722:219:50)
at http://localhost:3000/packages/iron_dynamic-template.js?d425554c9847e4a80567f8ca55719cd6ae3f2722:252:25
at null.<anonymous> (http://localhost:3000/packages/blaze.js?efa68f65e67544b5a05509804bf97e2c91ce75eb:2445:26)
at http://localhost:3000/packages/blaze.js?efa68f65e67544b5a05509804bf97e2c91ce75eb:1808:16
at Object.Blaze._withCurrentView (http://localhost:3000/packages/blaze.js?efa68f65e67544b5a05509804bf97e2c91ce75eb:2043:12)
at viewAutorun (http://localhost:3000/packages/blaze.js?efa68f65e67544b5a05509804bf97e2c91ce75eb:1807:18)
at Tracker.Computation._compute (http://localhost:3000/packages/tracker.js?517c8fe8ed6408951a30941e64a5383a7174bcfa:296:36)
at Tracker.Computation._recompute (http://localhost:3000/packages/tracker.js?517c8fe8ed6408951a30941e64a5383a7174bcfa:310:14)
from controller data start
from controller data end
from controller waitOn
from controller data start
from controller data end

我没有正确使用 Controller 吗?

最佳答案

如果无法看到您定义的使用这些路由 Controller 的其余代码(例如模板或路由定义),我无法准确说明数据函数被多次调用的原因。我怀疑您可能将 ProfileVerificationsController 与多个路由一起使用,在这种情况下,该 Controller 的 data 定义将被执行多次,每个路由使用该 Controller 一次.由于 data 定义是响应式(Reactive)的,当您浏览应用程序和数据更改时,这可能会导致定义的代码重新运行。

至于您的 Controller 定义,我建议进行一些修改以使代码更健壮和防弹。首先,ProfileController定义:

    ProfileController = RouteController.extend({
layoutTemplate: 'UserProfileLayout',
yieldRegions: {
'navBarMain': {to: 'navBarMain'},
'userNav': {to: 'topUserNav'},
'profileNav': {to: 'sideProfileNav'}
},
onBeforeAction: function() {
if(!Meteor.user()) {
Router.go(Router.path('login'));
this.redirect('login'); // Could do this as well
this.render('login'); // And possibly this is necessary
} else {
this.next();
}
}
});

请注意我更改的第一件事,将 yieldTemplates 更改为 yieldRegions。此拼写错误会阻止使用此路由 Controller 的模板中的区域正确填充所需的子模板。其次,在 onBeforeAction 定义中,我建议不仅使用 Underscore 检查 Meteor.user() 对象是否为 null,而且还检查它是否为 undefined。我所做的修改将允许您检查 Meteor.user() 对象的两种状态。最后,与其说是错别字更正,不如说是将用户引导至 login 路由的替代建议,您可以使用 this.redirect()this。 render() 函数而不是 Router.go() 函数。有关可以为路由/路由 Controller 定义的所有可用选项的更多信息,请检查 this出。

现在为 ProfileVerificationsController 定义:

    ProfileVerificationsController = ProfileController.extend({
waitOn: function() {
return Meteor.subscribe('userProfileVerification');
},
data: function() {
if(this.ready()) {
var verifiedEmail = Meteor.user().emails && Meteor.user().emails[0].verified ? Meteor.user().emails[0].address : '';
var verifiedPhoneNumber = Meteor.user().customVerifications.phoneNumber && Meteor.user().customVerifications.phoneNumber.verified ? Meteor.user().customVerifications.phoneNumber.number : '';

var data = {
verifiedEmail: verifiedEmail,
verifiedPhoneNumber: verifiedPhoneNumber
};
return data;
}
}
});

请注意我更改的一件事,即使用 if(this.ready()){} 包装 Controller 的 data 选项中定义的所有代码。这在使用 waitOn 选项时很重要,因为 waitOn 选项将一个或多个订阅句柄添加到路由的等待列表中,并且 this.ready() check 只有在等待列表中的所有句柄都准备就绪时才返回 true。确保使用此检查将防止在为路由构建数据上下文时意外未加载数据的任何情况。有关为路由/路由 Controller 定义订阅的更多信息,请查看 this出。

作为最后的建议,对于 ProfileController 中的 onBeforeAction 选项定义,我建议将它移到它自己的全局钩子(Hook)中,如下所示:

    Router.onBeforeAction(function() {
if(!Meteor.user()) {
Router.go(Router.path('login'));
} else {
this.next();
}
});

在全局 Hook 中定义此检查可确保您不必担心将 ProfileController 添加到所有路由,只是为了确保对所有路由运行此检查。每次访问一条路线时,都会对每条路线运行检查。不过,这只是一个建议,因为您可能有不这样做的理由。我只是想建议它,因为我确保为我开发的每个 Meteor 应用程序都这样做以提高安全性。

关于javascript - Meteor Iron 路由器钩子(Hook)被多次运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29017452/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com