【问题标题】:Rename files asynchronously in Node.js if destination files don't exist如果目标文件不存在,则在 Node.js 中异步重命名文件
【发布时间】:2019-12-28 16:32:40
【问题描述】:

仅当目标文件不存在时,我才尝试在 Node.js 中异步重命名文件。

我做了如下快速测试:

const fs = require('fs')

const files = [ 'file1', 'file2', 'file3' ]
const new_name = 'new-name' // same destination name for all 

fs.exists() - 已弃用

for (let file of files)

  fs.exists(new_name, (exists) => {
    if (!exists) fs.rename(file, new_name, (err) => {})
   })

fs.access() - 推荐

for (let file of files)

  fs.access(new_name, fs.constants.F_OK, (err) => {
    if (err) fs.rename(file, new_name, (err) => {})
  })

fs.move() - 来自fs-extra

const fs_extra = require('fs-extra')

for (let file of files) 

  fs_extra.move(file, new_name, { overwrite: false }, (err) => {})

每次所有 3 个文件都被覆盖并重命名为一个文件。


我相信这是因为所有exists 检查都比任何rename 发生更早触发。

我知道如何同步完成这项任务,但想确定没有合适的异步方式来执行此操作。

【问题讨论】:

  • 您是否考虑过为此使用异步等待?
  • 在 nodejs 中使用异步模块并使用 async.waterfall 。查看此链接以查看异步模块中的各种选项。 medium.com/velotio-perspectives/…
  • @cr05s19xx 不。遗憾的是,我不知道如何正确地做到这一点。

标签: javascript node.js asynchronous fs fs-extra


【解决方案1】:

@ponury-kostek 解决方案效果很好,并被标记为已接受的答案。

我最终得到了以下代码,因为它有点短:

async function rename_files() {

  for (let file of files)                
      await fs.move(file, new_name)
}
rename_files()  

【讨论】:

    【解决方案2】:

    你可以在文件重命名时创建Promiseresolve

    fs.rename(file, new_name, (err) => {
        resolve(); <------
    });
    

    或跳过重命名时

    fs.access(new_name, fs.constants.F_OK, (err) => {
        if (err) {
            return fs.rename(file, new_name, (err) => {
                resolve();
            });
        }
        resolve(); <------
    });
    

    完整代码

    (async () => {
        for (let file of files) {
            await new Promise((resolve) => {
                fs.access(new_name, fs.constants.F_OK, (err) => {
                    if (err) {
                        return fs.rename(file, new_name, (err) => {
                            resolve();
                        });
                    }
                    resolve();
                });
            });
        }
    })();
    

    如果您不想将async/awaitPromise 混合使用

    (async () => {
        function rename(file, new_name) {
            return new Promise((resolve) => {
                fs.access(new_name, fs.constants.F_OK, (err) => {
                    if (err) {
                        return fs.rename(file, new_name, (err) => {
                            resolve();
                        });
                    }
                    resolve();
                });
            });
        }
    
        for (let file of files) {
            await rename(file, new_name);
        }
    })();
    

    【讨论】:

    • 效果很好。感谢您的回答。你知道如何使用 async.waterfall 实现这一点吗?
    猜你喜欢
    • 2014-07-20
    • 2015-11-25
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    相关资源
    最近更新 更多