背景
随着我的应用程序的发展,我与AngularJS的挣扎越来越多,它承诺跨多个控制器和服务进行同步/排序。在下面的示例中,我有一个文章控制器ArticleController
和相关服务ArticleDataService
,它们在初始加载过程中
从服务器获取/加载文章,
从文章中选择第一篇文章,然后
使用当前文章currentArticle
从服务器获取相关图像。
问题
从服务器加载数据大约需要1秒钟返回商品记录,然后如上选择第一个商品,然后还从服务器返回相关的图像记录。问题在于,在该等待时间段内,第二个控制器(ImagesController
)在第二个服务模块(ImageDataService
)中查找缓存的数据,但找不到它,因为由于以下原因,第一个承诺显然未从Article Controller中解决:服务器延迟,因此ArticleController
尚未缓存图像数据,这会炸毁随后的所有图像相关代码。如您在下面看到的,如果我尝试在$q.when(cachedImages)
上返回cachedImages
,它将返回一个承诺,但是该承诺永远不会解决。由于两个控制器都使用单独的$ q解析序列,这是有道理的,但是如果没有构建超级控制器,我不确定如何解决序列问题。
编辑
我正在尝试解决n:n链接/排序问题
大多数教程或讨论都倾向于集中于1:1或1:n链接,这非常有效。没问题。
这是我遇到问题的n:n,即服务的ctrl,服务的服务和服务的n ctrl。我在n:n上可以找到的大多数内容都是基本的tut,它们加载了没有延迟问题的简单静态数组或对象。
尝试的方法
rootscope / watch:我已经在服务内部尝试了$rootscope.$watch()
事件以及在控制器中进行了监视,即在ImageDataService
内部的imageCached var上基于事件的方法,但是坦率地说,我发现这很麻烦,因为可能会产生不必要的开销,调试和测试问题,也就是说,它确实可以工作,但是当控制台记录一个深度嵌套的var时,我会不时看到很多迭代,这使事件方法看起来像黑盒子一样。
编辑-观看方法
示例:我可以将以下内容添加到第二个控制器ImageController
或有效的ImageDataService
中,就像$ emit一样,然后杀死该观察程序,但是正如我所说,这确实需要一些时间来管理相关方法,例如作为图表数据指令。另外,我想知道将承诺和事件混合在一起是不好的做法还是在JS中公认的最佳做法?
var articleModelListener = $scope.$watch(function () {
return ImageDataService.getImages();
},
function (newValue, oldValue) {
if (newValue !== undefined && newValue !== null) {
if (Object.keys(newValue).length > 0) {
iCtrl.dataUrls = newValue;
// kill $watcher
articleModelListener();
}
}
});
超时:我也试图将所有ImageController代码包装在超时中并也准备好文档,但是我发现这会进一步影响例如在我的Chart和Poll控制器中,我必须将指令包装在其他$ timeouts或$ intervals中,以针对ImagesController时间间隔进行调整,否则这些指令将无法正确加载DOM属性,因此,这会导致应用程序性能下降。
uber DataService服务或工厂数据解析:我试图解析uber DataServices服务提供程序中的所有数据,但是我发现所有控制器现在都遇到同样的问题,尽管uber服务解决了我现在需要与uber同步所需的排序问题和所有控制器。我知道异步...随时给我状态编程:)
问题与假设
假设:超时和间隔包装是不良做法/反模式,因为那是瀑布?
是遵守承诺的最佳方法吗?如果是,是否有办法在多个控制器/服务之间实现承诺的同步或说更好的顺序解决?还是我会继续使用旋转仪监视和控制器作用域监视来拒绝事件方法?
我的代码示例/问题如下:
请注意:
1.为了简洁起见,我删除了代码,即我没有测试此摘要代码,而是使用它来举例说明上述问题。
2.非常感谢所有帮助。对我滥用的任何术语表示歉意。
的HTML
<section ng-controller="MainController as mCtrl">
// removed HTML for brevity sakes
</section>
<section ng-controller="ImagesController as iCtrl">
// removed HTML for brevity sakes
</section>
Angular JS(1.4。*)
<pre><code>
angular.module('articles', [
])
.controller('ArticlesController', ['ArticleDataServices', 'ImageDataService', function(ArticleDataServices, ImageDataService) {
var mCtrl = this;
mCtrl.articles = {};
mCtrl.currentArticle = {};
mCtrl.images = {};
var loadArticles = function () {
return ArticleDataServices
.getArticles()
.then(function (articles) {
if(articles.data) {
mCtrl.articles = articles.data;
return mCtrl.articles[Object.keys(mCtrl.articles)[0]];
}
});
},
loadCurrentArticleImages = function (currentArticle) {
return ImageDataService
.getArticleImages(currentChannel)
.then(function (imagesOfArticles) {
if(imagesOfArticles.data) {
return mCtrl.images = imagesOfArticles.data;
}
});
},
cacheImages = function (images) {
return ImageDataService
.parseImages(images)
.then(function () {
});
};
loadChannels()
.then(loadArticles)
.then(loadCurrentArticleImages)
.then(cacheImages);
}])
</code></pre>
注意:在下面的
ImagesController
中,由于此控制器在第一个控制器仍在等待服务器中的数据(即cachedImages
或未返回承诺)之前执行其方法时,出现了问题。<pre><code>
.controller('ImagesController', ['ImageDataService', function(ImageDataService) {
var iCtrl = this;
mCtrl.images = {};
var getCachedImageData = function () {
return ImageDataService
.getCachedImageData()
.then(function (images) {
if(images) {
return mCtrl.images = images;
}
});
}
}])
.service('ArticleDataServices', ['$http',', $q', function($http, $q){
var model = this,
URLS = {
ARTICLES: 'http://localhost:8888/articles'
},
config = {
params: {
'callback': 'JSON_CALLBACK',
'method': 'GET',
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}
};
model.getArticles = function() {
config.params['url'] = URLS.ARTICLES;
return $http(config.params);
};
return {
getArticles: function () {
var deffered = $q.defer();
deffered.resolve(model.getArticles());
return deffered.promise;
}
}
}])
.service('ImageDataService',['$http',', $q', function($http, $q){
var model = this,
URLS = {
IMAGES: 'http://localhost:8888/images'
},
cachedImages,
config = {
params: {
'callback': 'JSON_CALLBACK',
'method': 'GET',
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}
};
model.getArticleImages = function(currentArticle) {
config.params['url'] = URLS.IMAGES + '/' . currentArticle.slug;
return $http(config.params);
};
// Return images or $q.when
model.getCachedImageData = function() {
if (cachedImages) {
return cachedImages
} else {
return $q.when(cachedImages);
}
};
model.setImageCache = function(images) {
cachedImages = images;
};
return {
getArticleImages: function (currentArticle) {
var deffered = $q.defer();
deffered.resolve(model.getArticleImages(currentArticle));
return deffered.promise;
},
setImageCache:function (images) {
return model.setImageCache(images);
},
getCachedImageData:function () {
return getCachedImageData();
}
};
}]);
</code></pre>
最佳答案
使用angular进行初始化时,您的问题对于人们很常见。正确的是您的服务中的退货保证为:
app.controller("AppController", function($scope, $ajax){
$ajax.call("/people", "", "POST").then(function(req) {
$scope.people = req.data;
});
});
app.factory("$ajax", function($http) {
function ajax(url, param, method) {
var requisicao = $http({
method: method,
url: url,
data:param
});
var promise = requisicao.then(
function(resposta) {
return(resposta.data);
}
);
return promise;
}
return({
call:ajax
});
});
请注意,仅在返回服务时填充变量。重要的是,将所有方法或其他任何使用此类变量的方法都放在Then方法中。这将确保这些其他方法仅在从后端返回后才执行
关于javascript - AngularJS n:n许诺和数据同步/排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33723172/