读取目录中的所有文件,将它们存储在对象中,然后发送该对象
我不知道这是否可能,但这里。 而使用callback则更加困难。
我有一个带有html文件的目录,我想通过node.js和socket.io以对象块的forms发送回客户端。
我所有的文件都在/ tmpl中
所以套接字需要读取/ tmpl中的所有文件。
对于每个文件,它必须将数据存储在一个以文件名为关键字的对象中,并将内容作为值存储。
var data; // this is wrong because it has to loop trough all files. fs.readFile(__dirname + '/tmpl/filename.html', 'utf8', function(err, html){ if(err) throw err; //filename must be without .html at the end data['filename'] = html; }); socket.emit('init', {data: data});
最后的callback也是错误的。 当目录中的所有文件都完成时,它必须被调用。
但是我不知道如何创build代码,谁知道这是可能的?
所以,有三个部分。 阅读,存储和发送。
这是阅读部分:
var fs = require('fs'); function readFiles(dirname, onFileContent, onError) { fs.readdir(dirname, function(err, filenames) { if (err) { onError(err); return; } filenames.forEach(function(filename) { fs.readFile(dirname + filename, 'utf-8', function(err, content) { if (err) { onError(err); return; } onFileContent(filename, content); }); }); }); }
这里是存储部分:
var data = {}; readFiles('dirname/', function(filename, content) { data[filename] = content; }, function(err) { throw err; });
发送部分取决于你。 您可能希望逐一发送或阅读完成后。
如果要在阅读完成后发送文件,则应使用fs
函数的同步版本或使用promise。 asynchronouscallback不是一个好的风格。
另外你问关于剥离扩展。 你应该逐个进行问题。 没有人会为你写一个完整的解决scheme。
这是前一个版本的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 ); });
假设你有另一个文件夹列表,你可以遍历这个列表,因为内部的promise.all将会以asynchronous的方式parsing每个文件夹:
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
会promiseAll
魔力。 它采用签名function(item,index,resolve,reject)
的函数块,其中item
是数组中的当前项, index
它在数组中的位置,并resolve
和reject
Promise
callback函数。 每个承诺将被推入当前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);
为了让代码在不同的环境中平滑运行 , path.resolve可以用在path被操纵的地方。 这里是更好的代码。
阅读部分:
var fs = require('fs'); function readFiles(dirname, onFileContent, onError) { fs.readdir(dirname, function(err, filenames) { if (err) { onError(err); return; } filenames.forEach(function(filename) { fs.readFile(path.resolve(dirname, filename), 'utf-8', function(err, content) { if (err) { onError(err); return; } onFileContent(filename, content); }); }); }); }
存储部分:
var data = {}; readFiles(path.resolve(__dirname, 'dirname/'), function(filename, content) { data[filename] = content; }, function(error) { throw err; });
Promise现代方法的另一个版本。 其他人基于Promise反应的时间越短越好:
const readFiles = (dirname) => { const readDirPr = new Promise( (resolve, reject) => { fs.readdir(dirname, (err, filenames) => (err) ? reject(err) : resolve(filenames)) }); return readDirPr.then( filenames => Promise.all(filenames.map((filename) => { return new Promise ( (resolve, reject) => { fs.readFile(dirname + filename, 'utf-8', (err, content) => (err) ? reject(err) : resolve(content)); }) })).catch( error => Promise.reject(error))) }; readFiles(sourceFolder) .then( allContents => { // handle success treatment }, error => console.log(error));