Это современная Promise
версия предыдущей, используя Promise.all
подход для решения всех обещаний, когда все файлы были прочитаны:
/**
* 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);
});
});
});
}
чтобы использовать его:
Так же просто, как делают:
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);
});
предположить, что у вас есть еще один список папок вы также можете пройти по этому списку, так как внутреннее обещание.все будет решать каждый из затем асинхронно:
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);
});
});
Как это работает
promiseAll
делает магию. Он принимает функциональный блок подписи function(item,index,resolve,reject)
, где item
- это текущий элемент массива, index
его позиция в массиве и resolve
и reject
функции обратного вызова Promise
. Каждое обещание будет выталкиваться в массиве при текущем index
и с текущим item
в качестве аргументов через вызов анонимной функции:
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);
Если синхронный доступ в порядке, вы можете пропустить обработчик события, используя (блокирование) 'readfileSync' и' readdirSync'. http://nodejs.org/docs/v0.4.8/api/fs.html#fs.readdirSync – rjz
Хорошо, я не знал о readdir, который может быть полезен. И каковы недостатки блокировки. Я думал, что весь узел node.js состоит в том, что он не блокирует? Почему мы можем внезапно блокировать. –
Для асинхронных обратных вызовов прочтите следующее: http://stackoverflow.com/questions/18983138/callback-after-all-asynchronous-foreach-callbacks-are-completed Существует много неправильных ответов, но некоторые из них верны. Один из них использует счетчики. – Vanuan