gpt4 book ai didi

javascript - 在AngularJS中,如何在所有 Controller 初始化后运行代码?

转载 作者:搜寻专家 更新时间:2023-11-01 04:30:21 25 4
gpt4 key购买 nike

我有一个由多个模块组成的单页 AngularJS 应用程序,其目的是为用户提供协作 pad(主小部件)和其他相关小部件(其他连接的用户、pad 元数据等)。

我选择拆分应用如下:

  • 1个托管服务的模块,负责公开pad组件的初始化方法
  • N 个模块托管自定义指令(及其 Controller ),对应于应用程序中的不同小部件
  • 1个模块负责收集参数和初始化pad组件

让我们通过假设我只有 1 个小部件来简化它,其唯一目标是向用户显示状态消息:“正在验证”、“已验证”、“错误”或“就绪”。

我选择在服务中使用订阅/通知模式,让小部件收到共享组件状态更改的通知。

服务:

angular.module("app.core").factory("padService", padService);
function padService() {
// Callback registration and notification code omitted
return {
initialize: function (authToken) { ... },
onAuthenticated: function (callback) { ... },
onReady: function (callback) { ... },
onError: function (callback) { ... }
};
}

小部件:

angular.module("app.widget").directive("widget", widget);
function widget() {
return {
templateUrl: 'app/widget.html',
restrict: 'E',
controller: widgetController
};
}
function widgetController($scope, padService) {
$scope.message = "authenticating";
padService.onAuthenticated(function (user) {
$scope.message = "authenticated";
// Do other stuff related to user authentication event
});
padService.onReady(function (padInstance) {
$scope.message = "ready";
// Do other stuff related to pad readiness event
});
padService.onError(function (error) {
$scope.message = "error";
// Do other stuff related to error event
});
}

现在“初始化器模块”以其最简单的形式从 URL 片段(类似于 OAuth2)中收集身份验证 token authToken 并简单地调用 padService.initialize(authToken);。请注意,它也可以是专用的身份验证弹出窗口,这就是为什么它驻留在自己的模块中的原因。

我的问题是我不知道将那段代码放在哪里。我尝试过的所有地方都导致在 Angular Bootstrap 过程中放置​​得太早和/或没有更新小部件:

angular.module("app.initializer").run(run);
function run($document, $timeout, tokenService, padService) {
// This does not work because run() is called before the
// controllers are initialized (widget does not get notified)
var authToken = tokenService.getTokenFromUrl();
padService.initialize(authToken);

$document.ready(function () {
// This does not work because angular does not detect
// changes made to the widget controller's $scope
var authToken = tokenService.getTokenFromUrl();
padService.initialize(authToken);

// This does not work in firefox for some reason (but
// does in chrome!)... except if I enter debug mode or
// set the timeout to a longer value, which makes it
// either really difficult to diagnostic or ugly as hell
$timeout(function () {
var authToken = tokenService.getTokenFromUrl();
padService.initialize(authToken);
}, 0);
});
}

最佳答案

The controllers are created synchronously (I assume), so there shouldn't be any difficulty to make some code run after that.

这是一个错误的假设。 AngularJS 框架在应用程序的生命周期中定期创建和销毁指令及其 Controller 。 ng-repeatng-ifng-include 等都创建和销毁包含指令的 DOM。如果您的“小部件”是 ng-repeat 的一部分,它的 Controller 会被实例化多次,一次是针对 ng-repeat 监视的列表中的每个项目。

要保留在应用程序的整个生命周期中持续存在的数据,请将其保存在服务中。 (或在 $rootScope 上;不推荐,但可以选择。) Controller 不能假定它们已在引导期间启动。他们需要“ catch ”并订阅更改。

将持久数据保存在工厂服务中,并提供settergetter函数。

angular.module("app").factory("padService", function () {
//Store service status here
var status = "none-yet";

function setStatus(s) {
status = s;
return status;
};

function getStatus() {
return status;
};

return {
setStatus: setStatus,
getStatus: getStatus
};
});

在您的“小部件”中,注入(inject)服务、订阅更改和“追赶”。

angular.module("app").directive("widget", function() {
function widgetController($scope, padService) {
//subscribe with $watch
$scope.$watch(padService.getStatus, function(newStatus) {
//catch-up and react to changes
case (newStatus) {
"authenticated":
// Do stuff related to authenticated state
break;
"ready":
// Do stuff related to pad ready state
break;
"error":
// Do stuff related to error state
break;
default:
// Do something else
}
$scope.message = newStatus;
};
};
return {
templateUrl: 'app/widget.html',
restrict: 'E',
controller: widgetController
}
});

当指令首先使用 AngularJS 框架 $watch 注册监听器时,执行 watch 函数(在本例中为 padService.getStatus),然后执行监听器函数.这允许指令“ catch ”服务的当前状态。

在每个摘要周期,AngularJS 框架执行 padService.getStatus。如果状态发生变化,框架将以新状态作为第一个参数执行监听器函数。这允许指令对更改使用react。

您不能假设指令及其 Controller 是同步创建的。但是您确实知道服务在被注入(inject) Controller 之前被实例化并且其构造函数被执行。

关于javascript - 在AngularJS中,如何在所有 Controller 初始化后运行代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34858440/

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