0

角 v.1.6.1

我正在尝试使用 $q.defer().promise 返回一个集合,但我只得到一条记录,而不是从我的服务返回的两条记录。

该模型:

angular.module('app').factory('User',
function() {

    /**
     * Constructor, with class name
     */
    function User(id, firstName, lastName, startDate) {
        // Public properties, assigned to the instance ('this')
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.startDate = startDate;
    }


    /**
     * Public method, assigned to prototype
     */
    User.prototype.getFullName = function() {
        return this.firstName + ' ' + this.lastName;
    };

    User.apiResponseTransformer = function (responseData) {
        if (angular.isArray(responseData)) {
            return responseData
                .map(User.build)
                .filter(Boolean);
        }
        return User.build(responseData);
    }

    /**
     * Static method, assigned to class
     * Instance ('this') is not available in static context
     */
    User.build = function(data) {
        return new User(
            data.Id,
            data.FirstName,
            data.LastName,
            data.StartDate
        );
    };


    /**
     * Return the constructor function
     */
    return User;
});

服务

(function () {
'use strict';

var serviceId = 'userService';
angular.module('app').factory(serviceId, ['common', '$http', 'config', 'User', userService]);

function userService(common, $http, config, User) {
    var $q = common.$q;
    var defer = $q.defer();

    var service = {
        getUsers: getUsers,
        getUser: getUser
    };

    return service;

    function getUser(id) {
        $http({
            method: 'get',
            url: config.remoteServiceName + 'users/' + id
        }).then(function (response) {
            defer.resolve(User.apiResponseTransformer(response.data));
        }).then(function (response) {
            defer.reject(response);
        });

        return defer.promise;
    }

    function getUsers(startDate) {
        $http({
            method: 'get',
            url: config.remoteServiceName +'users/',
            params: {
                startDate: startDate
            }
        }).then(function (response) {
            var users = [];
            angular.forEach(response.data, function (value, key) {             
                users.push(User.apiResponseTransformer(value));
            });
            defer.resolve(users);
        }).then(function(response) {
            defer.reject(response);
        });

        return defer.promise;
    }  
}
})();

视图方法

function getUser() {
        userService.getUser(1).then(function successCallback(data) {
            vm.user = data;
        }).catch(function () {
            log('An error occured trying to get user...');
        });
    }

    function getUsers() {
        userService.getUsers(new Date().toUTCString()).then(function successCallback(data) {
            vm.users = data;
        }).catch(function () {
            log('An error occured trying to get user...');
        });
    }

在视图内部,getUser 调用功能与预期相同,但 getUsers 仅从服务接收集合中的第一项。我已经验证 response.data 确实包含整个对象集合,并且这些对象被推送到 users 数组中。

即使调用 defer.resolve(response.data) 也只会发送集合中的第一项。

任何帮助表示赞赏!

4

1 回答 1

2

无需使用$q.defer基于 Promise 的 API 来制造 Promise。(如果对象有一个.then方法,它就是一个承诺。)

//ERRONEOUS
function getUser(id) {
      $http({
         method: 'get',
         url: config.remoteServiceName + 'users/' + id
      }).then(function (response) {
         defer.resolve(User.apiResponseTransformer(response.data));
      }).then(function (response) {
         defer.reject(response);
      });

      return defer.promise;
}

由于调用$http(config)可以与.then方法链接,因此它是一个返回的承诺。任何可以与.then方法链接的 API 调用都是基于 Promise 的 API。通过关注这一细节,可以确定未知 API 的性质。

//CORRECT
function getUser(id) {
    var promise = $http({
        method: 'get',
        url: config.remoteServiceName + 'users/' + id
    })

    var nextPromise = promise.then(function (response) {
        var value = User.apiResponseTransformer(response.data);
        //RETURN value to chain
        return value;
    }).catch(function (errorResponse) {
        //THROW to chain rejection
        throw errorResponse;
    });

    return nextPromise;
};

为了清楚起见,链条已被分解成一部分。$http 服务调用返回一个承诺。方法调用返回一个新的 Promise,该.thenPromise 解析为返回给其响应处理程序的值。然后将新的承诺返回给封闭函数。

在每一层嵌套都有一个返回(或抛出)语句是很重要的。

用法

getUser(id).then(function(transformedValue) {
    console.log(transformedValue);
});

因为调用 Promise 的.then方法会返回一个新的派生 Promise,所以很容易创建一个 Promise 链。

可以创建任意长度的链,并且由于可以使用另一个 Promise 来解决一个 Promise(这将进一步推迟其解决方案),因此可以在链中的任何点暂停/推迟对 Promise 的解决。这使得实现强大的 API 成为可能。

--AngularJS $q 服务 API 参考 - 链接承诺

于 2017-03-03T18:09:06.577 回答