您可以为此使用服务或工厂,并结合承诺:
您可以设置一个返回承诺的工厂,并创建一个全局函数(可从 3rd-party JS 访问)来解决承诺。
注意$rootScope.$apply()
通话。then
Angular在一个$apply
循环之前不会调用 Promise 的函数。请参阅$q
文档。
app.factory('fromoutside', function($window, $q, $rootScope) {
var deferred = $q.defer();
$window.injectIntoAngularWorld = function(obj) {
deferred.resolve(obj);
$rootScope.$apply();
};
return deferred.promise;
});
然后在您的控制器中,您可以请求fromoutside
服务并在数据到达时绑定到数据:
app.controller('main', function($scope, fromoutside) {
fromoutside.then(function(obj) {
$scope.data = obj;
});
});
然后在 Angular 之外的某个地方:
setTimeout(function() {
window.injectIntoAngularWorld({
A: 1,
B: 2,
C: 3
});
}, 2000);
这是一个小提琴。
就个人而言,我觉得这比通过 DOM 进入 Angular 控制器要干净一些。
编辑:另一种方法
Mark Rajcok 在评论中询问是否可以对其进行修改以允许多次获取数据。
现在,多次获取数据可能意味着增量更新,或更改对象本身,或其他事情。但需要发生的主要事情是将数据导入 Angular 世界,然后获得正确的 Angular 范围来运行它们$digest
的 s。
在这个 fiddle中,我展示了一种方法,当您可能只是从 angular 外部获取对 Array 的更新时。
它使用了与上面的 Promise 示例类似的技巧。
这是主要工厂:
app.factory('data', function($window) {
var items = [];
var scopes = [];
$window.addItem = function(item) {
items.push(item);
angular.forEach(scopes, function(scope) {
scope.$digest();
});
};
return {
items: items,
register: function(scope) { scopes.push(scope); }
};
与前面的示例一样,我们将一个函数附加到$window
服务(全局公开它)。新位公开了一个register
函数,想要更新的控制器data
应该使用它来注册自己。
当外部 JS 调用 Angular 时,我们只需遍历所有已注册的作用域并在每个作用域上运行摘要以确保它们已更新。