2017-08-03 50 views
2

這是我的javascript代碼至今:異步讀取多個文件中的for循環

文件是路徑的數組到HTML文件

我想3H公司,是HTML文件的所有3H公司標籤的數組。

function getH2OfFiles(files) { 

    return new Promise((resolve, reject) => { 
    let h3s = []; 
    for (let i = 0; i < files.length; i++) { 
     fs.readFile(path.join(__src, 'documentation', files[i]), 'utf8', (err, data) => { 
     if (err) throw err; 
     if (data.match(/<h3>(.*)<\/h3>/)) { 
      //console.log("->", { file: files[i], h3: data.match(/<h3>(.*)<\/h3>/)[1] }) 
      h3s.push(data.match(/<h3>(.*)<\/h3>/)[1]); 
     } 
     }) 

    } 
    resolve(h3s); 
    }); 
} 

它似乎沒有在for循環中工作(因爲它是異步的),但它是如何實現的?

+1

您將需要'Promise.all'這裏。 – georg

+0

@georg:只有他/她承諾 - 如果'readFile'。 –

+0

[關於正則表達式和HTML的強制性警告](https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags#1732454) –

回答

2

一種在承諾世界for循環對應的是Promise.all,經常與.map結合。在你的情況,編寫處理一個文件中的函數,例如

function getH3OfFile(fileName) { 
    return new Promise((resolve, reject) => { 
     fs.readFile(path.join('.....', fileName), 'utf8', (err, data) => 
      err 
       ? reject(err) 
       : resolve(data.match(/<h3>(.*)<\/h3>/)) 
     ); 
    }); 
} 

,然後將其應用到文件列表:

let fileNames = [...] 

Promise 
    .all(fileNames.map(getH3OfFile)) 
    .then(h3s => ...) // h3s is an array of matches 

(以防萬一你不知道,這裏還有readFileSync )。

+0

大概想過濾掉' null's。 –

+0

@ T.J.Crowder:當然,留作練習。 – georg

1

你大部分時間都在那裏,你只需要跟蹤你得到的回調數量並等待解決,直到你全部獲得了。此外,使用reject(err)而不是throw err,如果有一個問題:(注意,我還保存第一次調用的結果match而不是使正則表達式運行兩次)

function getH2OfFiles(files) { 

    return new Promise((resolve, reject) => { 
    let h3s = []; 
    let complete = 0; 
    for (let i = 0; i < files.length; i++) { 
     fs.readFile(path.join(__src, 'documentation', files[i]), 'utf8', (err, data) => { 
     if (err) reject(err);      // *** 
     const match = data.match(/<h3>(.*)<\/h3>/); 
     if (match) {        // *** 
      h3s.push(match[1]); 
     } 
     if (++complete === files.length) {   // *** 
      resolve(h3s);        // *** 
     }           // *** 
     }) 
    } 
    }); 
} 

,請注意,您可以按順序接收這些完成,因此h3s可能與文件無關(如果有的話)。

或者通過分而治之的簡化和給自己的readFile一諾指明分數版本,然後一次構建,所有文件的讀取結果,通過Promise.all

function readFilePromise(path, encoding) { 
    return new Promise((resolve, reject) => { 
    fs.readFile(path, encoding, (err, data) => { 
     if (err) { 
     reject(err); 
     } else { 
     resolve(data); 
     } 
    }); 
    }); 
} 

function getH2OfFiles(files) { 
    return Promise.all(files.map(file => readFilePromise(path.join(__src, 'documentation', file), 'utf8'))) 
     .then(results => { 
      const h3s = []; 
      results.forEach(result => { 
      const match = data.match(/<h3>(.*)<\/h3>/); 
      if (match) { 
       h3s.push(match[1]); 
      } 
      }); 
      return h3s; 
     }); 
} 

這也具有如下優點:Promise.all確保您以與原始承諾數組相同的順序接收數組(如果重要)。

(注:有庫是會答應,IFY的NodeJS的API。)

0

使用async npm模塊。他們提供同步迭代方法以及控制流的不同方法,如系列,瀑布,平行等。