Jest to nowoczesny Promise
wersja poprzedniego, stosując podejście Promise.all
rozwiązać wszystkie obietnice, gdy wszystkie pliki zostały przeczytać:
/**
* Promise all
* @author Loreto Parisi (loretoparisi at gmail dot com)
*/
function promiseAllP(items, block) {
var promises = [];
items.forEach(function(item,index) {
promises.push(function(item,i) {
return new Promise(function(resolve, reject) {
return block.apply(this,[item,index,resolve,reject]);
});
}(item,index))
});
return Promise.all(promises);
} //promiseAll
/**
* read files
* @param dirname string
* @return Promise
* @author Loreto Parisi (loretoparisi at gmail dot com)
* @see http://stackoverflow.com/questions/10049557/reading-all-files-in-a-directory-store-them-in-objects-and-send-the-object
*/
function readFiles(dirname) {
return new Promise((resolve, reject) => {
fs.readdir(dirname, function(err, filenames) {
if (err) return reject(err);
promiseAllP(filenames,
(filename,index,resolve,reject) => {
fs.readFile(path.resolve(dirname, filename), 'utf-8', function(err, content) {
if (err) return reject(err);
return resolve({filename: filename, contents: content});
});
})
.then(results => {
return resolve(results);
})
.catch(error => {
return reject(error);
});
});
});
}
Jak to Use:
tak proste, jak robi:
readFiles(EMAIL_ROOT + '/' + folder)
.then(files => {
console.log("loaded ", files.length);
files.forEach((item, index) => {
console.log("item",index, "size ", item.contents.length);
});
})
.catch(error => {
console.log(error);
});
Przypuszcza się, że masz inną listę folderów można również iteracyjne nad tej listy, ponieważ wewnętrznej obietnicy.wszystko rozwiąże każdego następnie asynchronicznie:
var folders=['spam','ham'];
folders.forEach(folder => {
readFiles(EMAIL_ROOT + '/' + folder)
.then(files => {
console.log("loaded ", files.length);
files.forEach((item, index) => {
console.log("item",index, "size ", item.contents.length);
});
})
.catch(error => {
console.log(error);
});
});
Jak to działa
promiseAll
robi magię. Zajmuje on blok funkcyjny podpisu function(item,index,resolve,reject)
, gdzie item
jest bieżącym elementem w tablicy, index
jego pozycją w tablicy, oraz resolve
i reject
funkcją wywołania zwrotnego. Każda obietnica zostanie wciśnięty w tablicy w bieżącym index
i aktualnym item
jako argumenty przez anonimowego wywołania funkcji:
promises.push(function(item,i) {
return new Promise(function(resolve, reject) {
return block.apply(this,[item,index,resolve,reject]);
});
}(item,index))
Wtedy wszystkie obietnice zostaną rozwiązane:
return Promise.all(promises);
Jeśli synchroniczny dostęp jest ok, można pominąć obsługi zdarzeń przy użyciu (blokowanie) metod 'readfileSync' i' readdirSync'. http://nodejs.org/docs/v0.4.8/api/fs.html#fs.readdirSync – rjz
Ok, nie wiedziałem o readdir, który może być pomocny. I jakie są wady blokowania. Myślałem, że cały punkt node.js był taki, że nie był blokowany? Dlaczego wszyscy możemy nagle zablokować. –
W przypadku asynchronicznych wywołań zwrotnych należy przeczytać: http://stackoverflow.com/questions/18983138/callback-after-all-asynchronous-foreach-allbacks-are-completed Istnieje wiele błędnych odpowiedzi, ale niektóre są poprawne. Jeden z nich używa liczników. – Vanuan