javascript - 让 fs.readme 与 async await 和 promisify 一起工作
问题描述
我正在尝试创建一个节点脚本,该脚本查看我最近创建的降价笔记的收件箱,在该笔记的顶部找到元数据,在该元数据中找到类别,然后将文件移动到其相关文件夹中。我不断收到错误消息:
(node:82025) UnhandledPromiseRejectionWarning: ReferenceError: paths is not defined
我相信这是因为我的代码没有等待 readFile 函数完成,尽管我已将其标记为 async/await 并将其包装在文件顶部的 promisify 中。有人可以指出我哪里出错了吗?下面的完整代码(其他依赖项用于另一个脚本):
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');
});
});
});
}
更新:遵循 Mestre San 的建议,今天早上开始工作。如果对任何人有用,这是我完成的代码。
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');
});
});
});
}
解决方案
您发布的片段绝对不完整,因为我们只能根据我们在这里看到的内容提供建议,这符合我的考虑:
您正在创建一个 promisified 函数,但您将它与回调一起使用。你应该选择一种风格。代码现在的方式是您的回调将永远不会被调用。您必须在
fs.readFile
那里使用或readFile(oldPath).then(data =>
.fs.promises.readFile
如果它在您正在使用的 Node.js 版本上可用,那就更好了我可以知道路径变量确实没有在
sortFiles
函数内部在线定义。代码在函数内部声明该变量,getNewPath
使其在函数内部不可用sortFiles
。该变量
notes
也未定义。代码notes
在函数内部创建变量markdownNotesOnly
。虽然不鼓励使用全局范围在函数之间共享这些值,但如果您选择这样做,您绝对应该在该函数之外使用let notes
.sortFiles没有被调用,但是由于它使用的是异步函数并且您没有将任何回调作为参数传递给它,因此它几乎可以像火一样工作并且忘记有点事情
sortFiles函数的名称中有 sort 这个词,但它的主体中有一个 rename 调用,即使您将来也会感到困惑。
但是,让您的代码停止抛出同样的错误的方法是执行以下操作:
'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')
})
})
})
}
推荐阅读
- reactjs - npm 包“watch”给出“没有这样的文件或目录”错误
- java - 尝试从下拉列表中添加到数据库
- batch-file - 从字符串中删除子字符串
- android - 在本机反应中为垂直和水平方向添加启动画面
- javascript - 为什么主进程和渲染进程调用的window.maximize()和macos上的动画不一样?
- sql - 如何根据上一个观察日期的某些标准选择最近的观察
- teradata - 代码 = 3504:选定的非聚合值必须是关联组的一部分。输出定向到答案集选项卡
- android - Flutter app gradle 构建异常失败
- ubuntu - 没有 ssh-tunnel 的 vagrant-vm 的 Hotmodule 自动重新加载 chrome
- python - 在 pandas 中创建一个分数列,其值取决于另一列的百分位数