Не удается получить массив из вложенных функций обещания - PullRequest
0 голосов
/ 13 июня 2019

Попытка вернуть список папок на диске, затем для каждой папки получить файлы в ней.Я хочу, чтобы набор результатов был одним массивом объектов.Окончательный результат вызова функции getPosts () - это обещание с пустым массивом.

Promise { [] }
  var accountId = req.body.accountId;

  var accountFilePath = 'accountFiles/' + accountId;

  function getPosts(accountFilePath) {
    return new Promise((resolve, reject) => {
      let postArray = [];
      fs.readdir(accountFilePath, (err, posts) => {
        for (let i = 0; i < posts.length; i++) {
          var postId = posts[i];
          var postFilePath = accountFilePath + '/' + postId;
          var postObject = getFiles(postId, postFilePath)
          postObject.then((response) => {
            postArray.push(response)
          })
        }
      });
      resolve(postArray)
    })
  }

  function getFiles(postId, postFilePath) {
    return new Promise((resolve, reject) => {
      fs.readdir(postFilePath, function (err, files) {
        postObject = {
          [postId]: files
        }
        resolve(postObject)
      });
    })
  }

  var fullPostArray = getPosts(accountFilePath)
  console.log(fullPostArray);

Желаемый результат:

[
  {
    'folder1': [
      'DSC0366.jpg',
      'DSC8874.jpg',
      'DSC8878.jpg',
      'DSC8951.jpg'
    ]
  },
  {
    folder2: [
      'nikki.jpg',
      'richard.jpg',
      'billy.jpg'
    ]
  }
]

1 Ответ

0 голосов
/ 13 июня 2019

Обещание было изобретено для решения так называемого ада обратного вызова: множественные асинхронные обратные вызовы запускаются в разное время, что затрудняет поддержание порядка. В то время как вы пытались использовать обещания, вы выбрали их на неправильном уровне: у вас все еще есть различные асинхронные вещи, происходящие внутри обещания, и это усложняет ситуацию (и они идут не так). Вместо этого попытайтесь обернуть самые маленькие асинхронные задачи в обещания, в вашем случае это будет (1) чтение папки, (2) getFiles (что вы уже сделали):

  function readFiles(path) {
    return new Promise((resolve, reject) => {
     fs.readdir(path, (err, files) => {
       if(err) reject(err) else resolve(files);
     });
   });
 }

Теперь getPosts можно записать в виде цепочки многообещающих задач, и вы можете использовать Promise.all, чтобы превратить массив обещаний в одно обещание:

  function getPosts(accountFilePath) {
    return readFiles(accountFilePath).then(posts => { // ¹
     return Promise.all(posts.map(postId => { // ²
       var postFilePath = accountFilePath + '/' + postId;
       return getFiles(postId, postFilePath); // ³
    }));
   });      
  }

¹: сначала читаются файлы, а затем следующая задача выполнена. Если вы вернете Обещание из обратного вызова .then (как в этом случае), это обещание также будет приковано.

²: Затем каждое сообщение может быть сопоставлено с Обещанием (³), которое разрешается до желаемого результата, с помощью Promise.all, при котором цепочка обещаний приводит к массиву результатов.


Более новый синтаксис async / await облегчает этот путь (хотя логика остается неизменной):

 async function getPosts(accountFilePath) {
  const posts = await readFiles(accountFilePath);
  const result = await Promise.all(posts.map(postId => {
    const postFilePath = accountFilePath + '/' + postId;
    return getFiles(postId, postFilePath);
  }));
  return result;
}    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...