Promise嵌套深图

Promise nested deep map

我正在尝试使用 Promise 使事情变得简单,但它似乎是一个真正的承诺噩梦。我想我遗漏了一些东西。

我愿意:

  1. 在数据库中获取一些文章
  2. 查看找到的每篇文章并遍历 article.authors 数组。
  3. 为每篇文章获取数据库中的每位作者(包括author.images)
  4. 将第一步中的文章列表发回给客户,但更新为 article.authors.images

我尝试了几种使用 Map / Each / spread / Reduce / _.clone / _cloneDeep

的方法

但没有像预期的那样工作

任何帮助将不胜感激

return Promise.bind({})
        .then(function find_article(){
            return Article.find().sort(req.params.sort).skip(req.params.page).limit(req.params.limit).populateAll()
        }).then(function(articles){
            dataBack = articles
            var articlesPromise =  Promise.map(articles,function(article){
                console.log('------------');
                var AuthorsPromise = Promise.map(article.authors,function(author){
                    return User.findOne(author.id).populateAll().then(function(){
                    })
                })
                return Promise.all(AuthorsPromise).then(function(data){
                    console.log('*******************************');
                    console.log(data);
                    return data
                })

            })
            return Promise.all(articlesPromise).then(function(allArticles){
                    console.log('++++++++++++++++++++++++++++++');

                console.log(allArticles);
            })
        })
        .then(function(WhatIsInThere){
            console.log('somethinAfter');
            console.log(WhatIsInThere);
        })

我得到了类似的东西,但仍然没有用我仍然错过了 .all()

的要点

这不是一项微不足道的任务,您需要链接承诺并且很可能使用像 Promise.all() or jQuery.when()

这样的函数

您的代码应如下所示

// function that fetch from database and returns promise
function getArticleFromDatabase(articleId) {
    return new Promise();
}

// function that fetch from database and returns promise
function getAuthorFromDatabase(authorId) {
    return new Promise();
}

var articleIds = [1, 2, 3]; // lets have some array with article ids
// then turn it into array of promises
var articlePromises = articleIds.map(function(articleId) {
    var articlePromise = getArticleFromDatabase(articleId);
    // return the promise
    return articlePromise.then(function(articleData) {
        // here we have available complete article data
        var articleAuthors = articleData.authors; // supose it's array of author ids
        // lets turn it into author data promises
        var authorsPromises = articleAuthors.map(function(author) {
            return getAuthorFromDatabase(author.id);
        });

        // return new Promise, so our first promise of article data
        // will return promise of article data with authors data
        return Promise.all(authorsPromises)
            .then(function(fullfilledAuthorsData) {
                // fill in authors data
                articleData.authors = fullfilledAuthorsData;
                // return complete article data with authors data
                return articleData;
            });
    });
});

Promise.all(articlePromises).then(function(fullfilledArticleData) {
    // here you have available complete article data from all articles
    // fullfilledActicledata is array mapped from initial array of ids
    // so fullfilledActicleData[0] has data for articleIds[0],
    // fullfilledActicleData[1] has data for articleIds[1] etc.
    // You can use the fullfilledArticleData freely.
});

基于您的代码

// this method obviously returns Promise already
var articlesPromise = Article
    .find()
    .sort(req.params.sort)
    .skip(req.params.page)
    .limit(req.params.limit)
    .populateAll();

// attach callback via .then()
articlesPromise
    .then(function(articles) {   
        // here we have fullfilled articles data already
        var articlesWithAuthorsPromises = articles.map(function(article) {
            var authorsPromises = article.authors.map(function(author) {
                return User.findOne(author.id).populateAll();
            });

            return Promise.all(authorsPromises)
                  .then(function(fullfilledAuthors) {
                      article.authors = fullfilledAuthors;
                      return article;
                   })
        })

        // return new Promise
        return Promise.all(articlesWithAuthorsPromises)
    })
    // attach another callback via .then()
   .then(function(fullData) {
        console.log(fullData);
    })
    // you should also listen for errors
    .catch(errorCallback)