2017-03-01 20 views
0

我想通過fs調用一個空文件夾的http請求。我們假設沒有子文件夾。因爲forEach不是異步的,我選擇使用asynceach而不是forEach。代碼如下:通過異步解除文件夾的鏈接速度非常慢

後端:

router.post('/emptyDir', function (req, res, next) { 
    console.log("router.post /emptyDir"); 
    var dir = req.body.dir; 
    var fs = require('fs'); 
    var async = require('async'); 
    fs.readdir(dir, function (err, files) { 
     if (err) return console.log(err); 
     console.log(JSON.stringify(files)); 
     async.each(files, function (file) { 
      fs.unlink(dir + file, function (err) { 
       if (err) return console.log(err); 
       console.log(dir + file + " is removed"); 
      }) 
     }, function (err) { 
      if (err) return console.log('A file failed to be removed'); 
      console.log('All files have been successfully removed'); 
      return res.json(dir); 
     }) 
    }); 
}); 

前端:

this.rewriteAllFiles = function (files) { 
    return $http.post('/emptyDir', { dir: prefix + idP + "/" }) 
     .then(function (res) { 
      console.log("emptyDir finished"); 
      ... 

我運行測試與包含2個文件的文件夾。它首先顯示沒有在瀏覽器日誌和以下日誌在後端:

router.post /emptyDir 
["index.html","script.js"] 
public/tmp/BGMTbU0RbeHdLAMjAAAD/index.html is removed 
public/tmp/BGMTbU0RbeHdLAMjAAAD/script.js is removed 

然後2分鐘後,它顯示在瀏覽器日誌emptyDir finished,並在後臺顯示再次router.post /emptyDir

router.post /emptyDir 
[] 
All files have been successfully removed 

我不明白爲什麼/emptyDir叫兩次,爲什麼需要這麼長...

因此,沒有人知道哪裏錯了?

編輯1:我意識到使用Array.forEach至少可以用於我的測試。但我不確定它是否是邏輯上正確。在files.forEach的塊已完成之前,以下函數是否可以返回

router.post('/writeFiles', function (req, res, next) { 
    console.log("router.post writeFiles"); 
    var dir = req.body.dir, files = req.body.files; 
    var fs = require('fs'); 
    files.forEach(function (file) { 
     fs.writeFile(dir + file.name, file.body, function (err) { 
      if (err) return console.log(err); 
      console.log(dir + file.name + " is written"); 
     }) 
    }); 
    console.log("All files have been successfully written"); 
    return res.json(dir); 
}) 

回答

0

取消鏈接是異步這樣你的整個foreach循環是「在同一時間」比你的代碼的其餘部分運行,這對READDIR和每一個功能幾乎不是「同步」節點相同。

我想你可能會考慮使用Promises。您可以爲每個解除鏈接的文件創建一個Promises數組。然後,您將使用Promise.all()等待所有Promise的完成(或失敗)。

事情與此類似(這將需要一些「重組」,但它的想法):

router.post('/emptyDir', function (req, res, next) { 
    console.log("router.post /emptyDir"); 
    var dir = req.body.dir; 
    var fs = require('fs'); 
    fs.readdir(dir, function (err, files) { 
     if (err) return console.log(err); 
     console.log(JSON.stringify(files)); 
     var unlinkQueue = files.map(function(file) { 
      return new Promise(function(resolve, reject) { 
       fs.unlink(dir + file, function (err) { 
        if (err) return reject(err); 
        console.log(dir + file + " is removed"); 
        resolve(file); 
       }); 
      }); 
     }); 
     Promise.all(unlinkQueue) 
      .then(function(files) { 
       console.log("All files have been successfully removed"); 
       res.json(dir); 
      }) 
      .catch(function(err) { 
       /* error */ 
      }); 
    }); 
}); 
+0

它的工作原理,謝謝... – SoftTimur

0

我意識到,比起the doc of async,我在async.each(files, function(file, callback) ...)忘記了callback。下面的代碼工程:

router.post('/emptyDir', function (req, res, next) { 
    console.log("router.post /emptyDir"); 
    var dir = req.body.dir; 
    var fs = require('fs'); 
    var async = require('async'); 
    fs.readdir(dir, function (err, files) { 
     console.log(JSON.stringify(files)); 
     async.each(files, function (file, callback) { 
      fs.unlink(dir + file, function (err) { 
       if (err) { 
        console.log(err); 
        callback(err) 
       } else { 
        console.log(dir + file + " is removed"); 
        callback(); 
       } 
      }) 
     }, function (err) { 
      if (err) return console.log('A file failed to be removed'); 
      console.log('All files have been successfully removed'); 
      return res.json(dir); 
     }) 
    }); 
});