使用角度路径解析中的多个promise修改项目数组

时间:2016-01-08 14:03:53

标签: javascript arrays angularjs angular-promise

在路由解析中,我需要进行API调用并返回一系列图书,如下所示:

{
    id: 1,
    name: 'Book name',
    authorId: 123
}

然后,我需要为books数组中的每本书进行另一个API调用,以返回作者姓名并将其添加到book对象。

{
    id: 1,
    name: 'Book name',
    authorId: 123,
    authorName: 'Author Name'
}

到目前为止,我有以下内容,但它不起作用,因为只有在已经返回书籍后才能解决authorPromise。如何正确拆分这些承诺并按预期修改图书对象?

resolve : {
    books: function ($stateParams, booksService, authorsService) {
        var books = [];
        var categoryId = $stateParams.categoryId;
        booksService.getBooksByCategory(categoryId)
            .then(function (response) {
                books = response.data;

                angular.forEach(books, function (book) {
                    var authorId = book.authorId;
                    authorsService.getAuthor(authorId)
                    .then(function (response) {
                        book.authorName = response.data.Name;
                    });
                });

                return books;
            });
    }  
}

1 个答案:

答案 0 :(得分:1)

基本上代码中有两个错误:

  • 工厂函数不返回任何值,您应该返回booksService生成的承诺。
  • 在第一个then调用的回调中,您将在任何异步调用完成之前返回数组,因此它将为空。要解决此问题,您可以使用$q.all(),这是一个接受Promise数组作为参数的函数,并创建一个新的promise,只有在解析了数组中的所有promise时才会解析。
编辑过的代码
resolve : {
    books: function ($q, $stateParams, booksService, authorsService) {
        var books = [];
        var categoryId = $stateParams.categoryId;
        return booksService.getBooksByCategory(categoryId)
            .then(function (response) {
                books = response.data;
                var promises = [];

                angular.forEach(books, function (book) {
                    var authorId = book.authorId;
                    var promise = authorsService.getAuthor(authorId)
                    .then(function (response) {
                        book.authorName = response.data.Name;
                    });
                    promises.push(promise);
                });

                return $q.all(promises).then(
                    function (res) {
                        return $q.resolve(books);
                    }
                );
            });
    }  
}