2017-02-13 440 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;