заставить fs.readme работать с asyn c await и promisify - PullRequest
0 голосов
/ 20 июня 2020

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

(node:82025) UnhandledPromiseRejectionWarning: ReferenceError: paths is not defined

Я считаю, что это потому, что мой код не ожидает, пока функция readFile завершит sh, несмотря на то, что я пометил его как async / await и завернул его в промисифицируйте вверху файла. Может ли кто-нибудь указать мне, где я ошибаюсь? Полный код ниже (другие зависимости относятся к другому сценарию):

    const fs = require('fs');
    const path = require('path');
    const firstline = require('firstline');
    const moment = require('moment');
    const { promisify } = require('util');
    
    const readFile = promisify(fs.readFile);
    
    const pathToResources =
      '/Users/Rob/Library/Mobile Documents/9CR7T2DMDG~com~ngocluu~onewriter/Documents/Test/Resources/';
    
    function markdownNotesOnly(files) {
      return (notes = files.filter((file) => path.extname(file) === '.md'));
    }
    
    async function getNewPath(note) {
      let oldPath = path.join(__dirname, note);
      let paths = {};
      let newPath = '';
    
      readFile(oldPath, (err, data) => {
        if (err) throw err;
    
        let metadata = data
          .toString()
          .match(/-{3}\n.*\n-{3}/gms)
          .toString();
        let category = metadata.match(/#§-\d{3}-.*/);
    
        if (!category) {
          paths = { oldPath, newPath };
          return paths;
        }
    
        category = category.toString().substring(3);
        newPath = path.join(pathToResources, category);
        paths = { oldPath, newPath };
        return paths;
      });
    }
    
    function sortFiles(startPath) {
      fs.readdir(startPath, (err, files) => {
        if (err) throw err;
    
        markdownNotesOnly(files); // returns array called notes
    
        notes.map(async (note) => {
          await getNewPath(note);
    
          let { oldPath, newPath } = paths;
    
          fs.rename(oldPath, path.join(newPath, note), (err) => {
            if (err) throw err;
            console.log('File moved successfully');
          });
        });
      });
    }

Обновление: последовал совету местре Сана ниже и заработал сегодня утром. Вот мой готовый код, если он кому-нибудь пригодится.

import { readdir, rename } from 'fs';
import { promises as fsPromises } from 'fs';
import { resolve, extname, join } from 'path';
const __dirname = resolve();

const pathToResources =
  '/Users/Rob/Library/Mobile Documents/9CR7T2DMDG~com~ngocluu~onewriter/Documents/Test/Resources/';

function markdownNotesOnly(files) {
  let notes = files.filter((file) => extname(file) === '.md');
  return notes;
}

async function getPaths(note) {
  const metadataRegex = /-{3}\n.*\n-{3}/gms;
  const categoryRegex = /#§-\d{3}-.*/;
  let oldPath = join(__dirname, note);
  let newPath = '';

  const file = await fsPromises.readFile(oldPath);
  if (file instanceof Error) throw err;

  if (!file.toString().match(metadataRegex)) {
    let paths = { oldPath, newPath };
    return paths;
  }

  let metadata = file.toString().match(metadataRegex).toString();
  let category = metadata.match(categoryRegex);

  if (!category) {
    let paths = { oldPath, newPath };
    return paths;
  }

  category = category.toString().substring(3);
  newPath = join(pathToResources, category);
  let paths = { oldPath, newPath };
  return paths;
}

export function sortFiles(startPath) {
  readdir(startPath, (err, files) => {
    if (err) throw err;

    let notes = markdownNotesOnly(files);
    notes.map(async (note) => {
      let paths = await getPaths(note);
      let { oldPath, newPath } = paths;
      rename(oldPath, join(newPath, note), (err) => {
        if (err) throw err;
        console.log('File moved successfully');
      });
    });
  });
}

1 Ответ

0 голосов
/ 20 июня 2020

Опубликованный вами фрагмент определенно неполный, поскольку мы можем дать совет только на основе того, что мы здесь видим, это мои соображения:

  1. Вы создаете обещанную функцию, но используете ее с обратным вызовом. Вам следует выбрать один стиль. Теперь, когда код выглядит так, ваш обратный вызов никогда не будет вызван. Вы должны использовать здесь fs.readFile или readFile(oldPath).then(data =>. Еще лучше было бы использовать fs.promises.readFile, если он доступен в версии Node.js, которую вы используете

  2. Я могу сказать, что переменная paths действительно не определена в строке внутри функции sortFiles. Код объявляет эту переменную внутри функции getNewPath, что делает ее недоступной внутри функции sortFiles.

  3. Переменная notes также не определена. Код создает переменную notes внутри функции markdownNotesOnly. Хотя совместное использование этих значений между функциями с использованием глобальной области видимости не рекомендуется, если вы решите это сделать, вам обязательно следует объявить его вне этой функции с помощью let notes.

  4. The sortFiles не вызывается, но поскольку он использует функцию asyn c, и вы не передаете ему обратный вызов в качестве аргумента, он будет в значительной степени работать как огонь и забыть кое-что

  5. Функция sortFiles имеет слово sort в своем имени, но в теле есть вызов переименования, который может сбить с толку даже вас в будущем.

Но способ заставить ваш код перестать выдавать ту же самую ошибку - это сделать что-то вроде этого:

'use strict'
const fs = require('fs')
const path = require('path')
// const firstline = require('firstline')
// const moment = require('moment')
const { promisify } = require('util')

const readFile = promisify(fs.readFile)

const pathToResources =
  '/Users/Rob/Library/Mobile Documents/9CR7T2DMDG~com~ngocluu~onewriter/Documents/Test/Resources/'

let notes, paths
function markdownNotesOnly (files) {
  'use strict'
  return (notes = files.filter((file) => path.extname(file) === '.md'))
}

async function getNewPath (note) {
  const oldPath = path.join(__dirname, note)
  // let paths = {}
  let newPath = ''

  return readFile(oldPath).then(data => {
    const metadata = data
      .toString()
      .match(/-{3}\n.*\n-{3}/gms)
      .toString()
    let category = metadata.match(/#§-\d{3}-.*/)

    if (!category) {
      paths = { oldPath, newPath }
      return paths
    }

    category = category.toString().substring(3)
    newPath = path.join(pathToResources, category)
    paths = { oldPath, newPath }
    return paths
  })
}

function sortFiles (startPath) {
  fs.readdir(startPath, (err, files) => {
    if (err) throw err

    markdownNotesOnly(files) // returns array called notes

    notes.map(async (note) => {
      await getNewPath(note)

      const { oldPath, newPath } = paths

      fs.rename(oldPath, path.join(newPath, note), (err) => {
        if (err) throw err
        console.log('File moved successfully')
      })
    })
  })
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...