Обещание было изобретено для решения так называемого ада обратного вызова: множественные асинхронные обратные вызовы запускаются в разное время, что затрудняет поддержание порядка. В то время как вы пытались использовать обещания, вы выбрали их на неправильном уровне: у вас все еще есть различные асинхронные вещи, происходящие внутри обещания, и это усложняет ситуацию (и они идут не так). Вместо этого попытайтесь обернуть самые маленькие асинхронные задачи в обещания, в вашем случае это будет (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;
}