解决 object 的正确方法将在解决不同的承诺后延长

Proper way to resolve an object going to be extended after resolving a different promise

我正在尝试制作一个 资源分页器 作为 restangular 的包装服务:

.factory('Collection', Collection)
 function Collection(Restangular) {
    var _route;
    ...

    function Collection(collectionName) {
        if (typeof collectionName === "undefined") {
            throw new Error("collection name is missing");
        }
        _route = collectionName;
    };

    Collection.prototype = {

        setData: function(response) {
            var data = response.data.plain();
            var _links = helpers.parse_link_header(response.headers('Link'));
            ...

            angular.extend(this, data);
        },

        load: function(perPage) {
            var scope = this;
            Restangular.all(_route).getList({'page':1, 'per-page':perPage})
            .then(function(collectionData) {
                scope.setData(collectionData);
            });
        },

        firstPage: function() {...},
        nextPage: function() {...}),
        ...

这就是我在控制器中使用它的方式:

vm.images = new Collection('images');
vm.images.load(2);

images.load() 将从服务器获取数据,一旦解析,它将把它发送到 setData() 方法,该方法将执行我需要的所有逻辑,如解析 headers 链接、元、..然后将使用我希望在我的控制器中拥有的所有数据扩展 class。

这行得通。它在页面加载时抛出 很少 逻辑错误,例如 Cannot read property 'next' of undefined 但是一旦模型得到扩展,一切正常,我可以在我的 HTML 查看文件 :

vm.images.nextPage();
vm.images.existNext();
vm.images.meta().$currentPage;

我的问题是:

在 ui-router 的状态 resolve 方法中初始化 my collection 的正确方法是什么并确保我的 object 在实例化控制器之前使用服务器响应进行了扩展?

到目前为止我尝试了什么:

我知道 promise 应该以某种方式 returned 所以我使 load 方法看起来像 :

load: function(perPage) {
    var deferred = $q.defer();
    var scope = this;
    _perPage = perPage;
    Restangular.all(_route).getList({'page':1, 'per-page':perPage})
    .then(function(collectionData) {
        var e = scope.setData(collectionData)
        deferred.resolve(e);
    }, 
    function(response) {
      console.log("Error with status code", response.status);
      deferred.reject();
    });
    return deferred.promise;
},

我做了 setData return 东西 :

setData: function(response) {
    ...
    var newClass = angular.extend(this, data);
    return newClass;
},

然后我将其添加到我的 $stateProvider.state :

resolve: {
  Collection: 'Collection',
  images: function(Collection){
    var images = new Collection('images');
    images.load(2);
    return images; 
  }
},

vm.images = images 控制器内部正在按预期获取数据,但抛出的错误与根本不添加数据时相同,因此其中的代码正在执行,但我不知道如何制作它等待使用服务器响应扩展模型。

如有任何帮助,我们将不胜感激 & 在此先致谢!

在解析器中,您应该return 加载 承诺:

images: function (Collection){
    var images = new Collection('images');
    return images.load(2);
}

另请注意,在加载函数中,您可以使用由 getList 编辑的承诺 return:

load: function (perPage) {
    return Restangular.all(_route).getList({'page':1, 'per-page':perPage})
        .then(scope.setData)
        .catch(function (response) {
            return $q.reject('Error with status code ' + response.status);
        });
}