在 angular 路由解析中使用多个承诺修改项目数组

Modify an array of items using multiple promises in angular route resolve

在路由解析中,我需要进行 API 调用和 return 书籍数组,如下所示:

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

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

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

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

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;
            });
    }  
}

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

  • 工厂函数没有 return 任何值,您应该 return booksService 生成的承诺。
  • 在第一个 then 调用的回调中,您在任何异步调用完成之前 returning 数组,因此它是空的。要解决这个问题,您可以使用 $q.all(),这是一个函数,它接受一个承诺数组作为参数,并创建一个新的承诺,该承诺仅在数组中的所有承诺都已解决时才解决。
编辑代码
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);
                    }
                );
            });
    }  
}