【问题标题】:How to handle multiple asynchronous operations that can both delete the same file?如何处理可以同时删除同一个文件的多个异步操作?
【发布时间】:2021-11-26 02:11:56
【问题描述】:

如果我有由 API 调用的异步函数,该函数会检查日志文件 current.log 的大小,如果超出限制,则应将其复制到 old.log 文件并删除 current.log 文件的内容之后。

function checkSizeCopyAndDelete(){
     if(size>1024){
          //delete old file contents 
          fs.truncate(oldLogFile,()=>{
               //copy current file contents to the old file
               fs.copyFile(currentLogFile, oldLogFile, ()=>{
                    //then delete the currentLogFile that was copied to the oldLogFile
                    fs.truncate(currentLogFile ,()=>{
                         //done, now we should add the new data to be logged to currentLogFile
                    })
               })
          })

     }
}

如果我使用fs.copyFile 而不是fs.copyFileSync, 如何处理事件循环基于checkSizeCopyAndDelete 找到两个不同的截断函数调用的场景 1024+,
然后执行 1 个截断调用并删除文件,然后甚至在第二个之前截断它确实复制了文件。

现在第二个截断仍然会被执行(并删除刚刚填充的新old.log文件),因为它不知道current.log文件大小变成了0,然后复制,留下old.log文件包含新的 current.log 文件的内容,而不是包含应该存在但被删除的 1024+ KB 数据。

在这种情况下我必须使用同步版本吗?

【问题讨论】:

  • 在哪种情况下,API 会多次调用以同时完成特定工作?如果您使用的是 HTTP API,为什么要这样做? cron 工作不适合吗?在任何情况下,如果您在启动时阻止新操作会更好。

标签: node.js asynchronous logging fs


【解决方案1】:

您可以通过设置承诺互斥锁并不断附加到承诺链来强制异步操作​​按顺序发生。

let chkSzTex = Promise.resolve();
async function checkSizeCopyAndDelete(){
  return new Promise((resolve,reject) => {
    chkSzTex = chkSzTex.then(()=>new Promise((res2,rej2)=>{
      if(size<=1024)
        return res2();
      //delete old file contents 
      fs.truncate(oldLogFile,(err)=>{
        if(err)
          return rej2(err);
        //copy current file contents to the old file
        fs.copyFile(currentLogFile, oldLogFile, (err)=>{
          if(err)
            return rej2(err);
          //then delete the currentLogFile that was copied to the oldLogFile
          fs.truncate(currentLogFile ,(err)=>{
            if(err)
              return rej2(err);
            //done, now we should add the new data to be logged to currentLogFile
            res2();
          })
        })
      })
    }).then(resolve).catch(reject)
  })
}

【讨论】:

    猜你喜欢
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-02
    • 2021-12-06
    • 2018-06-08
    • 1970-01-01
    相关资源
    最近更新 更多