承诺嵌套深层地图

时间:2016-05-25 10:28:24

标签: javascript dictionary promise bluebird

我正在尝试使用Promise来制作一些简单的东西,但它似乎是一个真正的承诺噩梦。我想我错过了一些东西。

我想:

  1. 获取数据库中的一些文章
  2. 查看找到的每篇文章并迭代article.authors Array。
  3. 为每篇文章获取dataBase中的每位作者(包括author.images)
  4. 将第一步中的文章列表发送回客户端,但使用article.authors.images更新
  5. 我尝试了几种方法使用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()

    的观点

1 个答案:

答案 0 :(得分:2)

这不是一项微不足道的任务,你需要链接承诺,并且很可能使用像Promise.all()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)