2016-05-25 1 views
0

Я пытаюсь использовать Promise, чтобы сделать что-то легкое, но, похоже, это настоящий кошмар с обещаниями. Я думаю, что у меня что-то не хватает.Обезглавленная глубокая карта

Я хотел бы:

  1. Fetch несколько статей в базе данных
  2. Посмотрите в каждую статью нашли и перебрать article.authors Array.
  3. Fetch каждый автор в базе данных (в том числе author.images) для каждой статьи
  4. Отправить обратно клиент список статей, начиная с шагом один, но обновляются с article.authors.images

I судимым severals способами использования Карты/Каждый/распространение/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); 
     }) 

я получил что-то вроде этого, но все еще не работает я до сих пор отсутствую точку .Вса()

+0

Какую базу данных вы используете, это актуально, потому что способ, которым вы строите свои запросы, будет убивать ваш сервер, как только ваша база данных начнет расти. – Yerken

+0

Что касается вопроса, выполните раздельную настройку своей задачи на отдельные этапы. Шаг 1, извлеките статьи, используя запрос базы данных, завернутый в обещания. Шаг 2, функция, которая берет массив статей с использованием Promise.all, и для каждой статьи возвращает еще одно модульное обещание, Promise.all снова, которое берет автора и возвращает изображение автора при поиске db. Верхний уровень api вызовет первый модуль и добавит другие – Yerken

+0

Вам больше не нужно называть 'Promise.all', если вы уже использовали' Promise.map'. Обратите внимание: 'Promise.map (arr, f)' эквивалентен 'Promise.all (arr.map (f))' – Bergi

ответ

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) 
+0

Спасибо за ответ, что быстро. Дело в том, что у меня нет идентификаторов статьи, пока я не получаю их из базы данных. – Oldwo1f

+0

@ Oldwo1f Идентификация статьи не важна, они просто иллюстративны. Важная часть заключается в цепочке обещаний, поэтому в ответ на первое обещание, которое вы создаете и возвращаете другое обещание, которое имеет обратный вызов, объединяет данные от первого и второго обещаний и возвращает другое обещание полных данных. – Vaclav

+0

да, но когда я общаюсь с несколькими статьями и авторами, я не могу вернуть его вместе. Еще одна вещь заключается в том, что я использую Waterline ORM, и мне нужны объекты _.clone или toObject для переопределения свойств (см. Здесь http://stackoverflow.com/questions/26535727/sails-js-waterline-populate-deep-nested -соединение) – Oldwo1f

Смежные вопросы