Обещание, не преобразующееся в значение при возврате

#javascript #promise

#javascript #обещание

Вопрос:

У меня есть рекурсивная функция, которая рекурсивно корректно преобразует отображенный массив.

 const postCommentsRecursive = (author, permlink) => {
  return client.database.call('get_content_replies', [author, permlink])
    .then(replies => Promise.all(replies.map(r => {
      if (r.children > 0) {
        return postCommentsRecursive(r.author, r.permlink)
          .then(children => {
            r.replies = children;
            return r;
          })
      }else {
        return r;
      }
    })))
}
  

Но когда я добавил другую выборку данных, возврат из then остается обещанием:

 const postCommentsRecursive = (author, permlink) => {
  return client.database.call('get_content_replies', [author, permlink])
    .then(replies => Promise.all(replies.map(r => {
//NEW CODE START
      const votes = client.database
        .call('get_active_votes', [r.author, r.permlink])
        .then(av => {
          return av;
        });
      r['active_votes'] = votes;
//NEW CODE END
      if (r.children > 0) {
        return postCommentsRecursive(r.author, r.permlink)
          .then(children => {
            r.replies = children;
            return r;
          })
      }else {
        return r;
      }
    })))
}
  

av это значение массива, отлично. Но когда я добавляю его к объекту из votes , вместо этого это Promise .

Каждый replies дочерний объект по-прежнему преобразуется в значение, но внутри каждого r , когда я добавляю votes в r as r['active_votes'] = votes , значение, установленное в объекте, является Promise {<resolved>: Array(1)} .

введите описание изображения здесь

Я не могу понять, как получить фактическое Array(1) значение, а не Promise как значение. Как мне просто получить Array в качестве значения, а не Promise ?

Спасибо!

Комментарии:

1. Вы не можете избежать обещаний. Как только вы попали внутрь обещания — все остальное также должно быть внутри обещания. .then всегда возвращает обещание, поэтому вам нужно передать обработчики .then для обработки данных.

Ответ №1:

В вашем коде вы присваиваете r.votes значение Promise . Вместо этого вам нужно перейти к .then этому обещанию, если вы хотите изменить r . (Концептуально это то же самое, что вы делаете в r.children > 0 блоке)

       return client.database
        .call('get_active_votes', [r.author, r.permlink])
        .then(av => {
          // mutate r
          r.active_votes = av;
          // now return it so that this entire promise resolves with `r`
          return r;
        });
  

async/await обычно подобный код становится немного понятнее:

 r.active_votes = await client.database
        .call('get_active_votes', [r.author, r.permlink])
  

Комментарии:

1. Вы можете сделать then часть этого короче и менее читабельной: .then(av => (r.active_votes = av, r))

2. Куда я могу поместить асинхронную часть ожидания? ожидание не может быть самостоятельным … спасибо. Я думал об async / await, но не смог заставить его применить здесь.

3. Ваше первое решение работает, с некоторыми изменениями (нет возврата к client.database части. Большое вам спасибо! 🙂