【发布时间】:2016-06-15 04:19:35
【问题描述】:
我正在为 Angular 应用程序使用 UI-Router。我有通过$http 异步调用提取的数据,该调用用于创建各种连接对象。我的目标是有某种方法来创建这个对象并使其作为单例可用。尽管发生这种情况的机会很少,但我希望避免服务中的 socket 属性被异步分配的时间问题。当路由器中的不同状态想要获取或创建另一个连接对象时,它将通过单例实现,以便可以使用相同的连接而不是创建另一个连接。
下面是我尝试开始工作的一些代码的框架。我不确定该州的resolve 是否可以做些什么。
关于如何做到这一点有什么想法或建议吗?
var myapp = angular.module('me', ['ui.router'])
.service('connectionService', ['$http', function($http) {
var socket;
// Somehow call and store result of $http in a singleton
// Would the $http.get get put in some kind of function? If so, how should it get called
// and returned so that a user of the service can get the 'socket' object synchronously?
$http.get("something/that/returns/data")
.success(function (result) {
this.socket= createConnection(result.data);
})
.error(function (err) {
//handle error
})
var getSocket= function() {
if (!this.socket) {
return createNewSocket();
} else {
return this.socket;
}
}
}])
myapp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("home");
$stateProvider
.state('home', {
url: "/home",
templateUrl: "home.html",
resolve: {
socket: // ??? Can something be done here ???
},
controller: function(socket) {
// I can haz socket?
}
})
.state('nextState', {
url: "/next",
templateUrl: "next.html",
resolve: {
socket: // Should be the same socket object as from the home state
},
controller: function(socket) {
// I can haz same socket?
}
})
})
更新
在试图更好地解释问题的过程中,我已经更改了几次原始代码。 cmets 的人已经纠正了我所犯的明确错误。我已将上面的代码恢复到原来的样子,并在下面添加了新代码。我仍然遇到的问题是 ui-router 状态上的resolve 在进入控制器之前没有解决。因此,在应该解决的socket 对象上调用emit() 时,出现“无法读取未定义的属性'发射'”的错误。我还希望 socket 对象在状态之间是相同的对象。我将不胜感激任何其他建议或 cmet 引导我朝着正确的方向发展。
var myapp = angular.module('me', ['ui.router'])
.service('connectionService', ['$http', function($http) {
var socket;
// Somehow call and store result of $http in a singleton
// Would the $http.get get put in some kind of function? If so, how should it get called
// and returned so that a user of the service can get the 'socket' object synchronously?
$http.get("something/that/returns/data")
.then(function (result) {
socket = createConnection(result.data);
}, function (err) {
// handle error
});
var getSocket = function() {
if (!socket) {
// handle error
} else {
return socket;
}
}
}])
myapp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("home");
$stateProvider
.state('home', {
url: "/home",
templateUrl: "home.html",
resolve: {
socket: function(connectionService) {
return connectionService.getSocket();
}
},
controller: function(socket) {
socket.emit("some msg");
}
})
.state('nextState', {
url: "/next",
templateUrl: "next.html",
resolve: {
socket: function(connectionService) {
return connectionService.getSocket();
}
},
controller: function(socket) {
socket.emit("some other msg");
}
})
})
更新 2
可行的解决方案,但这不如Muli Yulzari 的答案优雅,该答案已被接受为正确答案。
我研究了创建自己的 Promise 并将其作为 ui-router 解决的问题返回。根据我所有的调试和堆栈跟踪,在状态之间只创建了一个连接,并且延迟进入控制器,直到连接解决。所以,我相信这是一个可行的解决方案。我还有一个代码版本,它在解决承诺之前处理连接上的onConnect 事件,但为了简洁起见,我将其省略了。
var myapp = angular.module('me', ['ui.router'])
.service('connectionService', ['$http', '$q', function($http, $q) {
var socket;
this.getSocket = function() {
if (!socket) {
var deferred = $q.defer();
$http.get("something/that/returns/data")
.then(function (result) {
socket = createConnection(result.data);
deferred.resolve(socket);
}, function (err) {
// handle error
deferred.reject(socket);
});
return deferred.promise;
} else {
return socket;
}
}
}])
myapp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("home");
$stateProvider
.state('home', {
url: "/home",
templateUrl: "home.html",
resolve: {
socket: function(connectionService) {
return connectionService.getSocket();
}
},
controller: function(socket) {
socket.emit("some msg");
}
})
.state('nextState', {
url: "/next",
templateUrl: "next.html",
resolve: {
socket: function(connectionService) {
return connectionService.getSocket();
}
},
controller: function(socket) {
socket.emit("some other msg");
}
})
})
【问题讨论】:
-
在 Angular 中,服务是单例的,所以这确实是你想要的。但是,您的服务构建方式存在一些问题;具体来说,您在回调中使用
.this将无法按预期工作,因为.this指的是回调,而不是父服务。此外,您应该考虑切换到.then,而不是已弃用的.success。 -
删除了已弃用的
.success并切换到.then承诺。 -
你还在promise中使用
.this,这是主要部分不起作用。 -
在角度服务和工厂中都是单例的。
-
如果您是 Javascript 新手,那么您将需要花一些时间了解
this的工作原理,因为它是常见的错误来源。
标签: javascript angularjs asynchronous angular-ui-router