Javascript 使用promises在angularJS中建模异步数据
我正在用angularJS开发一个单页应用程序,在存储异步数据方面遇到了问题 为了简单起见,我基本上有一个服务,它保存一些作为承诺返回的数据模型(因为它们可以在任何给定时间异步更新) 我有一个有角度的手表,当某些条件改变时,它会更新这些模型。 我还有一个角度表,当某些条件改变时,它会使用这些数据 我的问题是: 使用数据的手表在更新此数据的手表之前启动,导致它立即使用“过时”数据而不是新的承诺启动 代码示例:Javascript 使用promises在angularJS中建模异步数据,javascript,angularjs,promise,deferred,Javascript,Angularjs,Promise,Deferred,我正在用angularJS开发一个单页应用程序,在存储异步数据方面遇到了问题 为了简单起见,我基本上有一个服务,它保存一些作为承诺返回的数据模型(因为它们可以在任何给定时间异步更新) 我有一个有角度的手表,当某些条件改变时,它会更新这些模型。 我还有一个角度表,当某些条件改变时,它会使用这些数据 我的问题是: 使用数据的手表在更新此数据的手表之前启动,导致它立即使用“过时”数据而不是新的承诺启动 代码示例: angular.module('myApp', []) .controller('myC
angular.module('myApp', [])
.controller('myController', function($scope, $q, asyncDataService) {
// This watch is called whenever we need to update the asyncData
$scope.$watch('variableThatCausesUpdate', function(newValue) {
// Set the async data to a new unresolved promise to reflect
// its pending nature
var newAsyncDataDeferred = $q.defer();
asyncDataService.setAsyncData(newAsyncDataDeferred.promise);
// fetch the async data (in my case it is an $http request.
// newAsyncDataPromise is the $http promise)
var newAsyncDataPromise = fetchAsyncData();
// resolve the newData promise with the result from this fetch
newAsyncDataPromise.then(function(newAsyncDataResult) {
// At this point the data is up to date
newAsyncDataDeferred.resolve(newAsyncDataResult.data);
});
});
// This watch is called to perform some action,
// but is watching the same variable as update
$scope.$watchCollection('[variableThatCausesUpdate, someOtherVariable]', function(newValue) {
// We want to ensure that our asyncData is up to date,
// since we will be using it in our action
asyncDataService.getAsyncData().then(function(asyncData) {
// Firing with the "stale" promise since it occurs before update
someActionRequiringOurAsyncData(asyncData);
})
/*
However I can fix the issue by doing this
(since it will be put at the end of the event queue)
But this seems ugly and maybe is the result of a bad design?
setTimeout(function() {
asyncDataService.getAsyncData().then(function(asyncData) {
someActionRequiringOurAsyncData(asyncData);
})
}, 0)
*/
});
});
我可以通过在调用promise之前使用setTimeout 0来修复此问题,以确保首先进行更新,但这感觉很糟糕,我开始觉得我从错误的方向解决了问题
当然,我可以随时请求数据,但这将导致大量无关的请求
我不能只观察已解决承诺的结果,因为其他变量也可以触发此手表,所以它不仅在特定数据更新时触发。既然下面的集合中有相同的var,为什么不完全删除第一个观察者呢
angular.module('myApp', [])
.controller('myController', function($scope, $q, asyncDataService) {
// This watch is called to perform some action,
// but is watching the same variable as update
$scope.$watchCollection('[variableThatCausesUpdate, someOtherVariable]', function(newValue) {
// We want to ensure that our asyncData is up to date,
// since we will be using it in our action
asyncDataService.fetchAsyncData().then(function(asyncData) {
// Firing with the "stale" promise since it occurs before update
someActionRequiringOurAsyncData(asyncData);
})
});
});
首先,不要在Angular中使用
setTimeout
,使用$timeout
秒,在第一个承诺解决后,您可以在回调中启动第二个手表吗?此超时将无法确保您的数据是最新的。当你在你的本地机器上测试时,这会起作用…但是在100-200毫秒响应时间的真实环境中。你的架构很糟糕。我使用setTimeout是因为我不想触发不必要的摘要循环。除了触发摘要之外,还有什么理由使用$timeout吗?另外,为什么超时不能确保数据是最新的?更新和需要更新的操作总是在同一个摘要循环中触发,因此它只会将其中一个移动到事件循环的末尾。一旦更新被调用,承诺现在就无法解决,它将正确地等待它完成。它不依赖于超时的实际持续时间。也许我在这里遗漏了什么?这将解决必须使用超时的问题,但这意味着每次需要使用变量时我都会发出一个新的ajax请求(它使用得非常频繁,只是偶尔更新)。我想在本地缓存它,因为它只是偶尔更新。当前,它存储为已解决的承诺,直到需要更新为止,更新时为未解决的承诺,更新完成后再次为已解决的承诺。也许我应该设置缓存?但这可能会导致问题,因为同一请求可能并不总是有相同的响应。