2017-06-15 22 views
1

我有關於異步函數以及函數返回結果後如何發送內容的問題。這是我想要實現的:使用來自異步函數的數據

在節點I中處理GET請求的過程中,讀取文件夾的內容,並返回該文件夾中的文件。接下來,我想遍歷該文件夾中每個文件的統計信息,僅加載在特定時間段內創建的文件,並最終將這些文件中的數據作爲對請求的響應發送。它看起來是這樣的:

array = [] 

fs.readdir(path, function(err, items) { 
    items.forEach(function(item) { 
     fs.stat(path, function(err, stats) { 
      if (period check) { 
       array.push(data) 
      } 
     }) 
    }) 
} 

res.send(array) 

這種做法最終發送一個空數組,我已經看了成這裏似乎是解決方案的承諾,但我不能讓他們在這種情況下工作。使用fs.statSync而不是fs.stat確實有效,但這大大降低了性能,感覺應該可以通過Promises實現,但我不知道如何實現。

有沒有人爲此提供解決方案?


編輯:關於對標記爲重複的問題,我想那裏第一次的答案來解決我的問題,但沒有成功。我的問題有一些嵌套函數和循環,比給出的例子更復雜。

+0

看看異步庫,eachSeries方法 – yBrodsky

回答

1

使用這個,如果你喜歡一個Promise爲基礎的方法:

var path = require('path') 

fs.readdir(myPath, function(err, items) { 
    var array = []; 

    Promise.all(items.map(function(item) { 
     return new Promise(function(resolve, reject) { 
      fs.stat(path.resolve(myPath, item), function(err, stats) { 
       if (err) { 
        return reject(err) 
       } 

       if (/* period check */) { 
        array.push(data) 
       } 

       resolve() 
      }) 
     }) 
    })).then(function() { 
     res.send(array) 
    }).catch(function(error) { 
     // error handling 
     res.sendStatus(500) 
    }) 
} 
+0

好吧,我完成了更新。讓我知道這是否適合你 –

+0

謝謝,這工作!你有使用路徑包的具體原因嗎?我只是連接字符串以獲得完整路徑。 – Evertvdw

+0

@Evertvdw它只是通用的,並確保文件分隔符的跨平臺兼容性,它們並不總是正斜槓。 –

0

這裏是我的建議。

// This is a new API and you might need to use the util.promisify 
 
// npm package if you are using old node versions. 
 
const promisify = require('util').promisify; 
 
const fs = require('fs'); 
 

 
// promisify transforms a callback-based API into a promise-based one. 
 
const readdir = promisify(fs.readdir); 
 
const stat = promisify(fs.stat); 
 

 
const dataProm = readdir(path) 
 
    .then((items) => { 
 
    // Map each items to a promise on its stat. 
 
    const statProms = items.map(path => fs.stat(path); 
 
    // Wait for all these promises to resolve. 
 
    return Promise.all(statProms); 
 
    }) 
 
    // Remove undesirable file stats based on the result 
 
    // of period check. 
 
    .then(stats => stats.filter(stat => periodCheck(stat))); 
 

 
// dataProm will resolve with your data. You might as well return it 
 
// as is. But if you need to use `res.send`, you can do: 
 
dataProm.then((data) => { 
 
    res.send(data); 
 
}, (err) => { 
 
    // If you go away from the promise chain, you need to handle 
 
    // errors now or you are silently swallowing them. 
 
    res.sendError(err); 
 
});

這裏是朝着util.promisify包我指的是一個鏈接。如果您使用節點v8 +,則不需要它。如果你這樣做,不要忘記用require('util.promisify');替換require('util').promisify;