$q defer 和 promises 以及如何使用它们在视图呈现之前为控制器加载数据
Posted
技术标签:
【中文标题】$q defer 和 promises 以及如何使用它们在视图呈现之前为控制器加载数据【英文标题】:$q defer and promises and how to use them to load the data for a controller before the view is rendered 【发布时间】:2012-08-31 17:04:23 【问题描述】:这是我发现的最相关的东西:https://***.com/a/11972028/110233
当我只想返回一个东西时,它似乎工作正常,但是当其他东西依赖于第一件事时,我不确定如何返回多个东西。
由于这有点迟钝,这里有一个关于我目前正在做的事情的小例子:
window.EventRosterCtrl = ($scope, subevent) ->
$scope.subevent = subevent
EventRosterCtrl.resolve =
subevent: (SubEvent, $route) ->
deferred = $q.defer()
SubEvent.get subevent_id: $route.current.pathParams.subevent_id, (subevent) ->
deferred.resolve subevent
return deferred.promise
这是我想做的一个例子:
window.EventRosterCtrl = ($scope, subevent, addresses) ->
$scope.subevent = subevent
$scope.addresses = addresses
EventRosterCtrl.resolve =
subevent: (SubEvent, $route) ->
deferred = $q.defer()
SubEvent.get subevent_id: $route.current.pathParams.subevent_id, (subevent) ->
deferred.resolve subevent
return deferred.promise
addresses: (User) ->
deferred = $q.defer()
# how do you get subevent called first and how would you access it here?
for participant in subevent.participants
User.get user_id: participant.user, (user) ->
addresses[participant._id] = user.address
deferred.resolve addresses
return deferred.promise
【问题讨论】:
【参考方案1】:您需要使用 .then() 链接承诺
var promise = firstOperation(); 承诺 = promise.then(函数(值) // 做更多的工作 返回值; // 它可以是另一个promise ); 回报承诺; // 当两个步骤都解决时,这一个将被解决【讨论】:
@Justen,我不知道 Coffescript,但是您示例的最后一行可能类似于return deferred.promise.then(function(value) return value; )
,即 promise.then()
返回一个新的承诺。
那行不通。解析是一个将键映射到函数的对象,子事件中的延迟将无法在另一个键映射中访问【参考方案2】:
好的,因此您无法以这种方式控制它,但想到的解决方法(当一个解决方案首先取决于另一个完成时)只需将所有内容放在一个对象中并解决它。最终对我最有效的是提供服务,但要遵循我原来的例子:
window.EventRosterCtrl = ($scope, info) ->
$scope.subevent = info.subevent
$scope.addresses = info.addresses
EventRosterCtrl.resolve =
info: (SubEvent, User, $route, $q) ->
deferred = $q.defer()
resolvedInfo =
SubEvent.get subevent_id: $route.current.pathParams.subevent_id, (subevent) ->
resolvedInfo.subevent = subevent
for participant in subevent.participants
User.get user_id: participant.user, (user) ->
addresses[participant._id] = user.address
if addresses.length is subevent.participants.length
resolvedInfo.addresses = addresses
deferred.resolve resolvedInfo
return deferred.promise
【讨论】:
【参考方案3】:EventRosterCtrl 仅在子事件准备好时才被初始化,所以以下应该可以工作:
window.EventRosterCtrl = ($scope, subevent) ->
$scope.subevent = subevent
for participant in subevent.participants
User.get user_id: participant.user, (user) ->
$scope.addresses[participant._id] = user.address
EventRosterCtrl.resolve =
subevent: (SubEvent, $route) ->
deferred = $q.defer()
SubEvent.get subevent_id: $route.current.pathParams.subevent_id, (subevent) ->
deferred.resolve subevent
return deferred.promise
【讨论】:
这仍然会有闪烁,因为$scope.addresses
在控制器和页面渲染之后解析。以上是关于$q defer 和 promises 以及如何使用它们在视图呈现之前为控制器加载数据的主要内容,如果未能解决你的问题,请参考以下文章