Как вернуть значения из вложенного обещания?

У меня есть набор ID фильмов в Redis: [1,2,3,4] и набор хешей с актуальными данными. Теперь я хочу получить все данные фильма для идентификаторов за один раз.

Я пытаюсь использовать промисы bluebird, но я застрял. Пока что у меня есть:

  function allMovies() {
    var movies, movieIds;
    return client.smembersAsync('movies.ids').then(function(ids) {
      movieIds = ids;
      movies =  _.map(movieIds, function(id) {
         var movie;
         return client.hmgetAsync("movies:" + id, 'title', 'description', 'director', 'year').done(function(data) {
           movie = data;
           return {
                 title: data[0], 
                 description: data[1], 
                 director: data[2],
                 year: data[3]
               };
          });
          return movie;
        });
    })

Проблема в том, что я пытаюсь, что я всегда получаю новое обещание, в то время как меня просто интересует JSON после завершения всех операций.

Кто-нибудь здесь может пролить свет на это?


person poseid    schedule 17.10.2013    source источник


Ответы (2)


В bluebird есть более приятный способ сделать это:

function allMovies() {
    return client.smembersAsync("movies.ids").map(function(id){
        return client.hmgetAsync( "movies:" + id, 'title', 'description', 'director', 'year');
    }).map(function(data){
        return {
            title: data[0],
            description: data[1],
            director: data[2],
            year: data[3]
        };
    });
}
person Esailija    schedule 19.10.2013
comment
{ isFulfilled: true, isRejected: false, fillmentValue: [], rejectionReason: undefined } - person poseid; 20.10.2013
comment
@poseid, как ты используешь функцию allMovies()? Если вы используете его как allMovies().then(function(movies){console.log(movies)}), то это серьезная ошибка. Однако на самом деле похоже, что вы используете его как console.log(allMovies()) - функция не возвращает фильмы, она возвращает обещание для фильмов. - person Esailija; 20.10.2013
comment
оба приводят к этому пустому Array:ma.then(function(m) { console.log(m) }) и ma.allMovies() с обещанием ma от allMovies. Я зарегистрирую ошибку в Github. - person poseid; 20.10.2013
comment
спасибо - github.com/petkaantonov/bluebird/issues/ - person poseid; 20.10.2013

Если Bluebird согласуется с Q в этом вопросе, нужно просто взять ваш массив обещаний и превратить их в обещание для массива результатов. Обратите внимание на добавление Q.all в ваш пример, возврат внутри обработчика и использование then вместо done для связывания обещания фильма.

function allMovies() {
    var movies, movieIds;
    return client.smembersAsync('movies.ids').then(function(ids) {
        movieIds = ids;
        movies =  _.map(movieIds, function(id) {
           var movie;
           return client.hmgetAsync("movies:" + id, 'title', 'description', 'director', 'year')
           .then(function(data) {
               return {
                   title: data[0], 
                   description: data[1], 
                   director: data[2],
                   year: data[3]
                };
            });
        });
        return Q.all(movies);
    })
person Kris Kowal    schedule 18.10.2013