2017-02-13 331 views
0

嗨,所以我一直在嘗試使這個嘗試使用異步模塊並不真正知道如何將其轉換爲一個試圖承諾它並沒有真正工作,我認爲我做錯了所以我恢復的功能,它是在第一NodeJS等待異步功能完成foreach

的方式基本上我想等到ReadJson()函數與閱讀在陣列中的所有JSON文件來完成,然後做其他的功能,如editjson等

代碼:

App.js

const Reader = require('./Reader'); 
Reader.ReadJson(); 

Reader.js

const fsp = require('fs-promise'); 
const JsonFiles = ['json1.json', 'json2.json', 'json3.json', 'json4.json']; 
const JsonContents = []; 
class Reader { 
    static ReadJson() { 
     JsonFiles.forEach(name => { 
      let FileDir = "D:\\Development\\Java\\" + name; 
      fsp.readJson(FileDir).then(contents => { 
       if (contents) { 
        JsonContents.push(contents); 
        console.log(`Loaded >> ${name} ${Reader.JsonContents.length}/${JsonFiles.length}`); 
       } 
      }); 
     }); 
     console.log('Done Reading Json Content!'); 
     //Other functions 
    } 
} 
Reader.JsonContents = JsonContents; 
module.exports = Reader; 

所以基本上輸出爲:

Done Reading Json Content! 
Loaded >> json1.json 1/4 
Loaded >> json2.json 2/4 
Loaded >> json3.json 3/4 
Loaded >> json4.json 4/4 

當我需要它是:

Loaded >> json1.json 1/4 
Loaded >> json2.json 2/4 
Loaded >> json3.json 3/4 
Loaded >> json4.json 4/4 
Done Reading Json Content! 

謝謝:)

+1

http://stackoverflow.com/questions/18983138/callback-after-all-asynchronous-foreach-callbacks-are-completed? –

+1

關於如何對像您一樣的異步操作循環進行排序,stackoverflow中已經有數十個問題,並且已經有超過數十個答案。我建議你找到他們並向他們學習。 – jfriend00

+1

一個解決方案:[只有在異步獲取請求完成時繼續循環](http://stackoverflow.com/questions/33662425/only-continue-for-loop-when-async-get-request-finishes/33662492#33662492) – jfriend00

回答

4

返回一個承諾,跟蹤你在0的進度並僅當JsonContents長度與JsonFiles長度相同時才解析它。

const fsp = require('fs-promise'); 
const JsonFiles = ['json1.json', 'json2.json', 'json3.json', 'json4.json']; 
const JsonContents = []; 
class Reader { 
    static ReadJson() { 
     return new Promise((resolve, reject) => { 
      JsonFiles.forEach(name => { 
       let FileDir = "D:\\Development\\Java\\" + name; 
       fsp.readJson(FileDir).then(contents => { 
        if (contents) { 
         JsonContents.push(contents); 
         console.log(`Loaded >> ${name} ${Reader.JsonContents.length}/${JsonFiles.length}`); 
        } 
        if (JsonContents.length == JsonFile.length) { 
         return resolve(JsonContents); 
        } 
       }).catch(err => { 
        return reject(err); 
       }); 
      }); 
     }); 
    } 
} 
Reader.JsonContents = JsonContents; 
module.exports = Reader; 

然後在你的應用程序中使用它:

const Reader = require('./Reader'); 
Reader.ReadJson().then(() => { console.log('Done Reading Json Content!'); }); 

另一種選擇是使用Promise.all,因爲你正在使用fs-promise,不過雖然它可以與forEach來完成,一個普通for循環是更好地在這裏。

const fsp = require('fs-promise'); 
const JsonFiles = ['json1.json', 'json2.json', 'json3.json', 'json4.json']; 
const JsonContents = []; 
class Reader { 
    static ReadJson() { 
     var promises = []; 
     for (let i = 0; i < JsonFiles.length; i++) { 
      let FileDir = "D:\\Development\\Java\\" + JsonFiles[i]; 
      promises.push(fsp.readJson(FileDir).then(contents => { 
       if (contents) { 
        JsonContents.push(contents); 
        console.log(`Loaded >> ${JsonFiles[i]} ${Reader.JsonContents.length}/${JsonFiles.length}`); 
       } 
      })); 

     } 
     return Promise.all(promises); 
    } 
} 
Reader.JsonContents = JsonContents; 
module.exports = Reader; 
+0

真棒剛剛學到了新東西,SRS謝謝! – Premt

+0

當'fsp.readJson()'已經做出承諾時,這是一種反模式來創建包裝承諾。如果你想要順序操作,你可以鏈接這些承諾。 – jfriend00

+0

@ jfriend00這就是'Promise.all'示例的目的,還有一個遞歸承諾選項,我沒有提到,所以它不會是「複雜」的解決方案。 –

1

作爲附錄Ron Dadon's Promise.all方法....

Bluebird承諾庫提供像Promise.mapPromise.filter一些輔助功能,可以移除大量的無極陣列處理代碼鍋爐板的。

const Promise = require('bluebird'); 
const fsp = require('fs-promise'); 
const path = require('path'); 


class Reader { 

    static readFiles(jsonPath, jsonFiles){ 
    let fileReadCount = 0; 
    return Promise.map(jsonFiles, name => { 
     let filePath = path.join(jsonPath, name); 
     return fsp.readJson(filePath); 
     }) 
     .filter((content, index, length) => { 
     if (!content) return false; 
     console.log(`Loaded >> ${jsonFiles[index]} ${index+1}/${length}`); 
     return true; 
     }) 
    } 

    static readJson() { 
    return this.readFiles(this.jsonPath, this.jsonFiles).then(contents => { 
     console.log('Done Reading Json Content!', contents); 
     return this.jsonContents = contents; 
    }) 
    } 

} 

Reader.jsonFiles = ['json1.json', 'json2.json', 'json3.json', 'json4.json']; 
Reader.jsonPath = 'D:\\Development\\Java'; 

module.exports = Reader;