Преобразование обратных вызовов для цикла for и рекурсии в обещания

1

Я написал функцию, выполняющую рекурсивно, чтобы найти файлы, чье имя включает данный мир. Я не понимаю, как работают обещания, и не может найти способ написать эту функцию с обещаниями, несмотря на жесткие попытки.

Я попытался вернуть обещание внутри функции findPath, но я не мог использовать его, поскольку extractFiles вызывает findPath. Я попытался создать список обещаний и вернуть все, но не смог добиться успеха.

Итак, как я мог написать эти функции с обещаниями?

const fs   = require('fs');
const path = require('path');


function findPath(targetPath, targetWord, done) {
  if (!fs.existsSync(targetPath)) return;

  fs.readdir(targetPath, (err, allPaths) => {
    if (err) done(err, null);

    for (aPath of allPaths) {
      aPath = path.join(targetPath, aPath);
      extractFiles(aPath, targetWord, done);
    }
  });

  function extractFiles(aPath, targetWord, done) {
    fs.lstat(aPath, (err, stat) => {
      if (err) done(err, null);

      if (stat.isDirectory()) {
        findPath(aPath, targetWord, done);
      }
      else if (aPath.indexOf(targetWord) >= 0) {
        let fileName = aPath.split('.')[0];
        done(null, fileName);
      }
    });
  }
}

findPath('../modules', 'routes', file => {
  console.log(file);
});
Теги:
callback
promise
es6-promise

1 ответ

0
Лучший ответ

Во-первых, чтобы сделать "основной" код более читаемым, я бы обещал функции fs

const promisify1p = fn => p1 => new Promise((resolve, reject) => {
    fn(p1, (err, result) => {
        if(err) {
            reject(err);
        } else {
            resolve(result);
        }
    });
});
const readdirAsync = promisify1p(fs.readdir);
const lstatAsync = promisify1p(fs.lstat);

Затем просто связывайте обещания так же, как с любыми другими обещаниями

const fs = require('fs');
const path = require('path');

function findPath(targetPath, targetWord) {
    const readPath = target => 
        readdirAsync(target)
        .then(allPaths => 
            Promise.all(allPaths.map(aPath => extractFiles(path.join(target, aPath))))
            .then(x => x.filter(x=>x)) // remove all the "false" entries - i.e. that don't match targetWord
            .then(x => [].concat.apply([], x)) // flatten the result
        );
    const extractFiles = aPath =>
        lstatAsync(aPath).then(stat => {
            if (stat.isDirectory()) {
                return readPath(aPath);
            } else if (aPath.includes(targetWord)) {
                return aPath.split('.')[0];
            }
            return false;
        });
    return readPath(targetPath);
}

findPath('../modules', 'routes')
.then(results => {
    // do things with the results - which is an array of files that contain the targetWord
})
.catch(err => console.error(err));

Совсем не так.

  • 0
    Еще раз спасибо Я не знал, как обещать основной функционал. У обещания есть какой-нибудь побочный эффект?
  • 0
    в этом случае нет - я не могу говорить во всех случаях: p обещания bluebird имеют встроенное обещание, которое, вероятно, гораздо более надежно, чем код, который я представил здесь - примечание: вам не нужно делать это таким образом что удаление кода обратного вызова от кода обещания облегчает чтение: p
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню