2017-02-13 6 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

Одно решение: [Только для цикла цикла, когда запрос async get request завершается] (http://stackoverflow.com/questions/33662425/only-continue-for-loop-when-async-get-request-finishes/33662492#33662492) – jfriend00

ответ

4

Верните обещание, отследите свой прогресс в forEach и разрешаем его, только если 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

Awesome только что узнал что-то новое, SRS Спасибо! – Premt

+0

Это анти-шаблон, создающий обещание оболочки, когда 'fsp.readJson()' уже выполняет обещания. Вы можете просто объединить эти обещания, если хотите последовательную работу. – jfriend00

+0

@ jfriend00 Это цель примера «Promise.all», а также есть вариант рекурсивного обещания, о котором я не упоминал, поэтому он не будет «более сложным» решением. –

1

В качестве дополнения к Ron Dadon's методу Promise.all ....

Bluebird библиотека обещание предоставляет некоторые вспомогательные функции, такие как Promise.map и Promise.filter, которые могут удалить много котельного пластины Promise кода обработки массива ,

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;