等待AngularJs服务$ resolved属性

时间:2015-06-24 10:30:42

标签: javascript angularjs asynchronous service

简单的问题,希望简单的解决方案。

我已经定义了多个服务来使用标签执行CRUD操作。

myApp.factory('GetTags', ['$resource', function ($resource) {
    return $resource('/myApp/API/Service/GetTagList', {}, {
        query: { method: 'GET', params: { groupId: 'groupId' }, }, isArray: true,
    });
}]);

myApp.factory('GetTag', ['$resource', function ($resource) {
    return $resource('/myApp/API/Service/GetTag', {}, {
        query: { method: 'GET', params: { tagId: 'tagId' }, }, isArray: true,
    });
}]);

myApp.factory('SaveTag', ['$resource', function ($resource) {
    return $resource('/myApp/API/Service/CreateTag', {}, {
        query: { method: 'POST', params: {/*createObj*/}, }, isArray: true,
    });
}]);

myApp.factory('UpdateTag', ['$resource', function ($resource) {
    return $resource('/myApp/API/Service/UpdateTag', {}, {
        query: { method: 'POST', params: {/*updateObj*/}, }, isArray: true,
    });
}]);

稍后在我的控制器中,我想在我的标签功能中执行类似的操作:

myApp.controller('myCtrl', ['$scope', '$routeParams', 'GetTags', 'GetTag', 'SaveTag', function ($scope, $routeParams, GetTags, GetTag, SaveTag) {
    ...
    // the goal of this function to keep a copy of
    // tags collection in client memory that mimics database
    // as well as adding selected tags to forms object
    // eg: myForm = {... Tags: [], ...}
    $scope.addtag = function (tag, subTag){
        ...
        if (!($scope.tags.length > 0)) {
            // skip checking and just add tag
            SaveTag.save({ Name: tag, Desc: "", ParentId: null, GroupId: 12, }, function (data) {
                console.log('save tag: ', data);
                //todo: should wait for data of save operation to comeback
                //      before moving on to requesting a full object
                GetTag.get({ tagId: data.Id, groupId: 12, }, function (data) {
                    console.log(' get tag: ', data);
                    tagObj = data.tag;
                });
            });
            // push newly created tag into tags collection
            $scope.tags.push(tagObj);
        ...
    };
    ...
});

我知道从我的控制器和相关功能中跳过了很多细节,但基本上我调用save后跟get的原因是因为tag + subTag场景。如果我要将复杂的对象传递给服务器进行处理,我不想使处理逻辑复杂化。假设我必须创建tag后跟subTag,javascript逻辑将如下所示:

...
// skip checking and just add tag and subTag
SaveTag.save({ Name: tag, Desc: "", ParentId: null, GroupId: 12, }, function (data) {
    //todo: should wait for data of save operation to comeback
    //      before moving on to requesting a full object
    GetTag.get({ tagId: data.Id, groupId: 12, }, function (data) {
        tagObj = data.tag;
    });
});
// push newly created tag into tags collection
$scope.tags.push(tagObj);

SaveTag.save({ Name: subTag, Desc: "", ParentId: tagObj.ParentId, GroupId: 12, }, function (data) {
    //todo: should wait for data of save operation to comeback
    //      before moving on to requesting a full object
    GetTag.get({ tagId: data.Id, groupId: 12, }, function (data) {
        tagObj = data.tag;
    });
});
// push newly created sub tag into tags collection
//todo: find parent index
$scope.tags[parent_index]["Elements"].push(tagObj);
...

但是如果你想知道,是的,我可以从save操作返回完整的对象,我可能会在不久的将来。减少异步调用的数量会更好,因为它们会影响整体性能。

但是现在我有几个问题:

  1. 目前我根据Angular文档声明了四种不同的服务。但如果它是一个具有多种功能的单一工厂,效率会更高。有人可以指出我在正确的方向。
  2. 当我调用data.$resolved服务时,是否有可能以某种方式停止并等待true属性转为save,以便我可以使用返回值调用get服务?或者也许有另一种方法可以做到这一点?
  3. 我正在深入研究Angular文档的$q,看看我是否可以利用这里的东西。
  4. 以防人们想知道我遇到了一些人们使用resolve属性$routeProvider的例子。不幸的是,我的场景是在用户交互过程中实时完成的。

    非常感谢任何帮助和所有建议。

    参考文献:

    1. AngularJs文档 - $q
    2. 非常好的解释和示例 - Using and chaining promises in AngularJS
    3. AngularJs文档 - $resource(最后一个示例显示了对$promise的使用)
    4. 更新

      看来我的预感是正确的。虽然我还没有上班,但我觉得答案在于$qchaining promises。现在我只需要让它发挥作用。

1 个答案:

答案 0 :(得分:0)

我不想回答我自己的问题,但我找到了有效的解决方案。

更新

好的,在挖掘并抓挠我的头后,我想出了这个代码:

__init__

在每次服务电话后注意// skip checking and just add tag SaveTag.save({ Name: tag, Desc: "", ParentId: null, GroupId: 12, }).$promise.then(function (data) { console.log('save tag: ', data); return data; }).then(function (data) { console.log('data: ', data.Id); GetTag.get({ tagId: data.Id, groupId: 12, }).$promise.then(function (data) { console.log(' get tag: ', data); return data; }).then(function (data) { console.log('data: ', data.tag); $scope.tags.push(data.tag); tagObj = data.tag; //todo: check for duplicate records // because repeater will complain and // it's pointless to have duplicate tags // on an item to begin with $scope.myForm.Tags.push(tagObj); }); }); $promise公开$promise返回的raw $http promise。这允许我使用$resource来链接其他逻辑。

所以,最后我最终做的就是改变我调用服务的方式。就是这样。